What causes the error below? I expect them both to return 2.
The Ruby Style Guide encourages no space between method name and parenthesis and accordingly Rubocop alerts with (safely auto-correctable) Lint/ParenthesesAsGroupedExpression when there is a space. But aligning with the Style Guide and having no space causes an actual error.
Integer.sqrt (4 if true) # 2
Integer.sqrt(4 if true) # syntax error, unexpected `if' modifier, expecting ')'
There is a related question 10 years ago which explores similar issues with a top-rated answer (2 votes) that was not accepted by the OP and I find unclear and hard to follow. The response to this question appears far clearer and more comprehensive. This question also references a nuance with Rubocop to be explored further.
The exhaustive explanation is quite complex, and requires digging into the Ruby BNF grammar, but the simple(r) explanation requires understanding two things:
function(args)
(without space and with parentheses), you are making Ruby guess what you mean. If you always use function(args)
, then Ruby KNOWS it is a function call with arguments. If you do not, then Ruby will have to guess what you mean.Just as an example. Take function 4 if true
. How would Ruby know what you mean here? Either it is function((4 if true))
, or function(4) if true
. Ruby has to "guess".
This was just an example, you have to combine this rule with rule number 2 below to understand the full picture:
If you accept these two rules, 1 and 2 together, you will understand that this:
function (control_statement)
Will be interpreted as this:
function((control_statement))
And therefore the only form which is allowed, if you plan to use a control statement in an argument list, is this one:
Integer.sqrt((4 if true))
All other forms will confuse the interpreter, and are not allowed by the Ruby grammar.