Reputation: 1644
I'm trying to understand the behaviour of arithmetic methods in Ruby. 1 .+ 2 .* 3
and 1 .+ (2) .* 3
and 1. + 2. * 3
and 1. + (2). * 3
and 1.+2.*3
all evaluate to 7, which means :+
is called before :*
, but 1.+(2).*3
evaluates to 9, which means :*
is called before :+
. Redefining both methods confirms that that's what's happening:
class Integer
alias_method :add, :+
alias_method :mul, :*
def + other
print :+
self.add other
end
def * other
print :*
self.mul other
end
end
puts 1 .+ 2 .* 3
puts 1 .+ (2) .* 3
puts 1. + 2. * 3
puts 1. + (2). * 3
puts 1.+2.*3
puts 1.+(2).*3
Output:
*+7
*+7
*+7
*+7
*+7
+*9
Why does it happen? Please point me where to find the relevant documentation. Thanks in advance.
Upvotes: 0
Views: 54
Reputation: 4348
Let's give an example that might be easier to understand
puts (2) + 3
vs
puts(2) + 3
In the first case, puts is followed by a space. Ruby takes it as omitted parentheses and evaluates the rest as the argument. It's equvalent to puts((2) + 3)
. 5 is printed. In the 2nd case, puts is immediately followed by a left parenthesis and ruby takes that as the beginning of method arguments. It's equivalent to (puts(2)) + 3
. It will print a 2 and then fail when trying to evaluate nil + 3
.
Now lets look at your examples
puts 1 .+ 2 .* 3
puts 1 .+ (2) .* 3
puts 1. + 2. * 3
puts 1. + (2). * 3
puts 1.+2.*3
In the first 6 cases, no method call is immediately followed by (
, all the parentheses are redundant. They are evaluated right to left. Note that not *
before +
, but right to left.
puts 1 .* 2 .+ 3 #=> 5
In the last example puts 1.+(2).*3
, the (
immediately follows .+
, so 2
is an argument to .+
. The result is then multiplied by 3.
Upvotes: 2