Don't worry. Ruby can be a little bit tricky in these cases. Let's examine the code line by line:
x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)
First line
First line is clear to you: it assigns an array of three elements to x. And that's just about it.
Second line
Second line calls the Object#send
method of x
passing a symbol (remember that everything that starts with :
is a symbol in ruby) :[]=
, 0
(a Fixnum
) and 2
(another Fixnum
).
Now you just have to take a look at what the send method does (as you said you've already done):
Invokes the method identified by symbol, passing it any arguments specified
This means that it will invoke the method identified by :[]=
and pass 0
and 2
to it. Now let's take a look at the Array#[]=
method. This method definition (which can be overloaded by you if you need to do so) is:
class Array
# ...
def []=(a, b)
# ...
end
end
This method is called by send
as x.[]=(0, 2)
which is pretty ugly if you ask me. That's why Ruby defines a syntactic sugar version: x[0] = 2
and in general:
x.[]=(a, b) --> x[a] = b
In the Array
case we also have the following:
x.[](a) --> x[a]
In both cases you are free to call whatever version makes sense to you in the specific context.
Third line
Now for the third and last line:
x[0] + x.[](1) + x.send(:[],2)
things gets really tricky. Let's divide it into:
x[0]
x.[](1)
x.send(:[], 2)
The first one is pretty straight forward. It returns the first element of the array.
The second one is the syntactic sugar that we have seen earlier which can be basically be converted into x[1]
which returns the second element of the array.
The third one uses Object#send
to call the method []
passing 2
to it. Which means that it calls x.[](2)
which means x[2]
.
Conclusion
The code
x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)
can be converted using:
x.send(:[]=, a, b) --> x.[]=(a, b)
x.send(:[], a) --> x.[](a)
x.[]=(a, b) --> x[a] = b
x.[](a) --> x[a]
to:
x = [1,2,3]
x[0] = 2
x[0] + x[1] + x[2]
which can be reduced to:
2 + 2 + 3
which results in:
7