Reputation: 789
The following code generates an output of 9. I understand send
is simply calling the method :[]
, but am confused how the parameters work.
x = [1,2,3]
x.send :[]=,0,4 #why is x now [4,2,3]
x[0] + x.[](1) + x.send(:[],2) # 4 + 2 + 3
How do line 2 and line 3 work?
Upvotes: 2
Views: 86
Reputation: 60068
x.send(:[]=, 0, 4)
is the same* as
x.[]=(0, 4)
which has the syntactic sugar of
x[0] = 4
which should be familiar from other languages. Parentheses are, of course, optional.
The .send
or .public_send
variety has the advantage that the method to invoke doesn't have to be hardcoded—it can come from a variable.
All this is congruent with ruby's paradigm of object orientedness: objects communicate with each other by sending messages, and the messages trigger code execution.
*almost, #send
will invoke private methods too
Upvotes: 4
Reputation: 87406
Line 2 is
x.send :[]=,0,4
That is basically a fancy way of writing this:
x[0] = 4
(Calling send
allows you to call private methods though, and that is one difference between the two syntaxes. Also, an object could conceivably override the send
method, which would break the first syntax.)
So line 2 has the effect of writing 4 into the first spot in the array.
Now on line 3, we see that we are adding up three things. Here is a list of the things we are adding:
x[0]
- the first elementx.[](1)
- another syntax for accessing elements, which accesses the second element. This syntax is a traditional method call, where the name of the method happens to be []
.x.send(:[], 2)
- This shows another feature of Ruby, which is the send
method. It accesses the third element.So the result will be 9, because the third line adds the first, second, and third elements of the array.
These examples appear to illustrate an interesting point about the design of the Ruby language. Specifically, array accesses are implemented as method calls. The preferred syntax for writing to an array is x[0] = 4
and the preferred syntax for reading is x[0]
, because that syntax is familiar to programmers from many different languages. However, reading and writing from arrays is actually implemented using method calls under the hood, and that's why it is possible to use some other syntaxes that look more like a traditional method call.
A traditional method call looks like this: object.foo(arg1, arg2, arg3, ...)
.
The send
thing shown above is a useful feature of Ruby that allows you to specify which method you are calling using a symbol, instead of forcing you to type the exact name. It also lets you call private methods.
Upvotes: 3
Reputation: 122383
Object#send
provides another way to invoke a method.
x.send :[]=,0,4
is saying, invoke []=
method on x
, and pass the argument 0
, 4
, it's equivalent to:
x[0] = 4
The name send
is because in Ruby, methods are invoked by sending a message to an object. The message contains the method's name, along with parameters the method may need. This idea comes from SmallTalk.
Upvotes: 4