Reputation: 2415
Given that you write the code on IRB:
array = [1,2,3]
array.each {|x| x > 2 ? puts "lower" : puts "higher"}
The program doesn't execute the line and it somehow according to the program is an incomplete line. Any help would be appreciated.
Upvotes: 1
Views: 768
Reputation: 11196
The previous answer explains clearly what is happening. However you may note that this syntax will also work, but here you are duplicating the method call on both sides of the ternary operator:
array.each {|x| x > 2 ? (puts "lower") : (puts "higher")}
By wrapping the duplicate method call on both sides, that code is executed on both sides. But it definitely is better style to do it the more correct way where you are passing the result of ternary to puts
array.each { |x| puts x > 2 ? "lower" : "higher"}
which is the same as:
array.each { |x| puts (x > 2 ? "lower" : "higher") }
The puts
method takes a single string argument and that's what we are passing it.
Upvotes: 1
Reputation: 211560
This is caused by ambiguous arguments. Ruby, unlike many other languages such as JavaScript, is really lax about requiring brackets puts x
and puts(x)
are equivalent. Where this breaks down is when it's not clear which are arguments, and which are part of other syntax.
For example, if f
is a method that takes 1-3 arguments and x
and y
are variables, then what is the meaning of:
f x, f x, y
Is that f(x, f(x,y))
, f(x), f(x), y
or f(x, f(x), y)
? Ruby throws an error rather than presume the wrong thing.
Easy fix is to eliminate the duplication of effort here and use a single puts
with a ternary used to determine the value:
array = [1,2,3]
array.each { |x| puts x > 2 ? "lower" : "higher"}
Now it works because there's no ambiguity on arguments, there's only one method call so it's easy.
Upvotes: 7