Parenthesis and nested calls

305 views
Skip to first unread message

Torben Hoffmann

unread,
Oct 11, 2013, 5:35:34 AM10/11/13
to elixir-l...@googlegroups.com
Hi,

I tried to run this:
iex(42)> [ integer_to_binary (5)]
["5"]
iex(43)> [ integer_to_binary (5), integer_to_binary(2)]
** (SyntaxError) iex:43: unexpected comma. Parentheses are required to solve ambiguity in nested calls. Syntax error before: ','


That seems a bit weird to me?!?! Is is not allowed to have a space between the function name and the ( in a list?

Cheers,
Torben

Peter Minten

unread,
Oct 11, 2013, 5:48:10 AM10/11/13
to elixir-l...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

It is a bit weird. Elixir's optional parentheses are what's causing
this weirdness.

Thing is, for the compiler you could have intended two things:

[ integer_to_binary((5), integer_to_binary(2))]
[ integer_to_binary(5), integer_to_binary(2)]

This is due to "(5)" being a valid expression in it's own right
(parentheses to override the default precedence rules).

Instead of choosing one or the other it complains forcing you to make
the choice explicitly.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.14 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJSV8lQAAoJEP1SBN68kfQv7rgQAIgHQhVB+F248Q8CFyjtMC4M
Ne8ZBF53aZUYwriKslwXfUrpHJgs9fl1VFxsVhyfvkI/XP8VcRf0QP6W3M95yEjN
2hpPrZ1YaamRaGHQLInp8S19MEZsWQVXxuAwJvqvpSHnW1ZPJSjPwI2/uhSQV1aP
xwPdCtVmSmqw3ojKwOMkval9z+06X0xKmAJXAuZBoEbiQK7HgsLXBSW54wYWYpj7
6YWO9EVUH8dijDnQ/Afpq5rzSUUVSojAzJR90tH3SD2o4pDyqV5x46bjDi7uHW15
B8jIyULbe8CPG5xzImJqCJptNcrOMfxqkkEN+j3J772wHeUrde2oPr/rv10vGL0f
2krJCWZsjOliLr8GEogtgFRXd0BzGByyxA57msRpYvjJSy7KQd1kXy0add/SMVbi
WipL1wvtAQ7kLnPvij7583JSEe/EOoK+dRfjzTWy62Kqlvzxqz/mFFelNAP/BL27
0vzWnUapHbC1LUL0J6XJ7Pw/WEE0SIvcic5DLQweGJ2iQAw93Ql/SzFbS4fImn3q
TuAEtIntf72zhpHRv6hbrwbGjHB5deHgqOqwUMtZeo1HR0fCU1WmAbhYUq8bj24b
Ismofh+vWbem8bftCaDEWwtzhVWeDD8PK/m2Ie59dVSqpOr3JoJbsz1LEjFnPV44
F6wFwdxUHWjDVBUKrbx4
=DC/u
-----END PGP SIGNATURE-----

Eric Meadows-Jönsson

unread,
Oct 11, 2013, 5:48:20 AM10/11/13
to elixir-l...@googlegroups.com

Elixir errors here because there is an ambiguity. It can be parsed as [ integer_to_binary( (5), integer_to_binary(2) ) ] or as [ integer_to_binary((5)), integer_to_binary(2) ].

Elixir has optional parenthesis for function calls, so when it sees a space after the function name it thinks you are calling the function with no parenthesis and the first argument will be parsed as an ordinary expression enclosed in parenthesis.



--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Eric Meadows-Jönsson

Alexei Sholik

unread,
Oct 11, 2013, 5:48:02 AM10/11/13
to elixir-l...@googlegroups.com
Try without a list:

iex(8)> integer_to_binary (5), integer_to_binary(2)
** (ArgumentError) argument error
    :erlang.integer_to_binary(5, "2")

Parentheses are implicit. "integer_to_binary (5)" is not separating paren from a function name, it's calling a function with the argument "(5)". So the invocation is parsed as integer_to_binary(5, integer_to_binary(2)). You can see that in the stacktrace.

You get a different error inside a list because that is a special case for that defined in the parser. I think the motivation is to avoid ambiguity – does this comma separate list elements or function arguments? See these tests https://github.com/elixir-lang/elixir/blob/master/lib/elixir/test/elixir/kernel/errors_test.exs#L80

When in doubt, use parentheses in calls, i.e. 

iex(8)> [integer_to_binary(5), integer_to_binary(2)]
["5", "2"]




--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.



--
Best regards
Alexei Sholik

José Valim

unread,
Oct 11, 2013, 5:49:29 AM10/11/13
to elixir-l...@googlegroups.com
Hello Torben!

When you write integer_to_binary (5) with a space in between, regardless if inside a list or not, Elixir treats that as invoking integer_to_binary/1 passing the (5) expression as argument. In order to make it clear:

iex> integer_to_binary(5, 2)
"101"
iex> integer_to_binary (5, 2)
** SyntaxError

The second example fails because (5, 2) is considered to be an expression (and an invalid one) and not arguments to integer_to_binary. Of course we could make it work but we often avoid such ambiguous cases to force everyone to share a similar code style. The only reason "integer_to_binary (5)" works is because "integer_to_binary EXPR" is a valid call anywhere.

TL;DR: Do not add a space in between the function name and its (arguments)




José Valim
Skype: jv.ptec
Founder and Lead Developer


On Fri, Oct 11, 2013 at 11:35 AM, Torben Hoffmann <torben...@gmail.com> wrote:

--

Torben Hoffmann

unread,
Oct 11, 2013, 5:51:44 AM10/11/13
to elixir-l...@googlegroups.com, jose....@plataformatec.com.br
Thanks for all the replies!

It's just one of those things than one needs to get used to.

Cheers,
Torben
Reply all
Reply to author
Forward
0 new messages