2.send("-", 3)
works, because -
is a method and 2
responds to that method:
2.respond_to?('-') #=> true
=
and +=
on the other hand are not methods:
2.respond_to?('=') #=> false
2.respond_to?('+=') #=> false
And even if =
was a valid method1, then
a = 2
a.send("=", 4)
would be equivalent to:
2.send("=", 4)
or simply:
2 = 4
In other words: it would redefine 2
as 4
, something Ruby doesn't allow you to do.
This is because variables (like a
above) are not objects. a.send
doesn't send a message to the variable a
, but to the object, a
is referring to (2
in the example).
The same applies to abbreviated assignment like +=
:
a = 2
a += 2
is equivalent to:
a = 2
a = a + 2
You can just rewrite it as:
a = 2
a = a.send("+", 2)
The assignment is not part of the method invocation.
1 you can actually define a method =
via define_method
:
class Foo
define_method('=') { |other| puts "`=' called with #{other}" }
end
But it is just an ordinary method. In particular, it does not and can not alter the variable the object was assigned-to or the object's identity:
f = Foo.new
#=> #<Foo:0x007ff20c0eeda8>
f.send('=', 123)
# `=' called with 123
#=> nil
f
#=> #<Foo:0x007ff20c0eeda8>