不用担心,在这些情况下Ruby可能有点棘手。让我们逐行检查代码:
x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)
第一行
第一行很清楚,它将一个由三个元素组成的数组分配给了x。就是这样。
第二行
第二行调用x
的Object#send
方法,传递一个符号(记住,在Ruby中,以:
开头的所有内容都是符号):[]=
、0
(一个Fixnum
)和2
(另一个Fixnum
)。
现在你只需要看一下send方法做了什么(就像你说过的那样):
调用由符号标识的方法,并传递任何指定的参数。
这意味着它将调用由
:[] =
标识的方法,并向其传递
0
和
2
。现在让我们看一下
Array#[]=
方法。此方法定义(如果需要,您可以进行
重载)为:
class Array
def []=(a, b)
end
end
这个方法被
send
作为
x.[]=(0, 2)
调用,如果你问我,这很丑陋。这就是 Ruby 定义一种语法糖版本的原因:
x[0] = 2
,通常来说:
x.[]=(a, b)
在Array的情况下,我们还有以下内容:
x.[](a)
在这两种情况下,您可以自由选择在特定上下文中有意义的版本。
第三行
现在是第三行也是最后一行:
x[0] + x.[](1) + x.send(:[],2)
事情变得非常棘手。让我们分成以下几部分:
x[0]
x.[](1)
x.send(:[], 2)
第一个很简单。它返回数组的第一个元素。
第二个是我们之前见过的语法糖,可以基本上转换为x[1]
,它返回数组的第二个元素。
第三个使用Object#send
调用方法[]
并将2
传递给它。这意味着它调用x.[](2)
,也就是x[2]
。
结论
该代码
x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)
可以使用以下方式进行转换:
x.send(:[]=, a, b) --> x.[]=(a, b)
x.send(:[], a) --> x.[](a)
x.[]=(a, b) --> x[a] = b
x.[](a) --> x[a]
到:
x = [1,2,3]
x[0] = 2
x[0] + x[1] + x[2]
可以简化为:
2 + 2 + 3
这将导致:
7
:[]=
也是send
方法的一个参数,所以可以这样使用:send(:[]=, 0, 2)
。 - Eureka