Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is space significant in this ruby method call?

Tags:

ruby

I'm writing a jsonify view in a Rails application. I have:

json.samba_secrets_present(not @idp_ad_info.samba_secrets.nil?)

That produces a syntax error:

app/views/idp_ad_infos/show.jsonify:7: syntax error, unexpected tIVAR, expecting '(' 

However,

json.samba_secrets_present (not @idp_ad_info.samba_secrets.nil?)

works fine. I would have expected that the first would be a method call to the samba_secrets_present method on the Jsonify::Builder object with a first argument of not idp_ad_info.samba_secrets.nil?. Why is the space significant?

like image 730
Sam Hartman Avatar asked Apr 27 '15 15:04

Sam Hartman


1 Answers

puts(not true)  #=> error
puts (not true) #=> false, CASE 2
puts(not(true)) #=> false

Ruby allows you to omit the parenthesis to call a method sometimes. Generally, if there's only one method call, you can omit the parenthesis. However, you cannot omit that when the method call is at the argument position of another method call (general case, see special case in Update section) because that would introduce ambiguity. Consider the following example:

puts(not true, false)
puts(some_method arg1, arg2)

The Ruby parser cannot determine whether the false (or arg2) is a argument of the inner method, or the outer puts, so it raises an error for these case. The parser doesn't have runtime context to determine the arity of the inner method, so it doesn't care whether it's a unary method (like not) or not.

Take CASE 2 as an example, that's interpreted as:

puts( (not false))

And you can write:

puts (not false), true, (not true)

they're all arguments to puts.

Some Ref: Positional Arguments

Update: toro2k commented that puts(system 'ls') works. That's because system accepts *args which will grab all the rest arguments. There won't be any arguments left for the outer method, definitely :). As a result, there's no ambiguity in that case.

def a *args
  args
end
p(a 1, 2, 3, 4) #=> [1, 2, 3, 4]

However, I'd vote to write clearer code with necessary parenthesis to make the code more readable.

like image 125
Arie Xiao Avatar answered Sep 20 '22 18:09

Arie Xiao