44

我刚刚阅读了sendRuby 中的内容,但在查看这段代码时我仍然感到困惑(它来自一个测验,但无论如何它已经过期了)

x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)

我知道第一行为 x 分配了一个数组,然后我根本不明白做什么:[] = ,0,2,我不明白为什么需要 send 我不明白x.[](1)最后做了什么和 x.send(:[],2)线

我真的很困惑,我只是无法在网上找到这些信息。

我找到了send 的作用,但我仍然有点困惑,并且对整个代码感到困惑。

4

5 回答 5

59

首先,像[](array index) 和[]=只是 Ruby 中的方法。x是一个Array,并且数组有一个[]=方法,它接受两个参数,一个索引和一个要设置的值。

Usingsend允许您使用任意参数将任意“消息”(方法调用)传递给对象。

x.send :sort例如,您可以调用将“排序”消息发送到数组。不过,排序不需要任何参数,所以我们不必向它传递任何额外的东西。

x#[]=,另一方面,接受两个参数。它的方法可以认为是这样的:

def []=(index, value)
  self.set_value_at_index(index, value)
end

所以,我们可以用 调用它send :[]=, 0, 2,就像调用x[0] = 2. 整齐吧?

于 2012-10-15T08:48:32.013 回答
24

在 Ruby 中,a[0] = 2实际上是a.[]=(0, 2).

知道了这一点,这就是你的第二行所做的——它[]=使用元编程调用带有两个参数的方法,正如你猜对的那样。

这与您的第三行相同:a[0]是 Ruby 中的语法糖 for x.[](0).

以下代码与您的示例更简单等效:

x = [1, 2, 3]
x[0] = 2
x[0] + x[1] + x[2]
于 2012-10-15T08:48:04.823 回答
22

不用担心。在这些情况下,Ruby 可能有点棘手。让我们逐行检查代码:

x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)

第一行

第一行对您来说很清楚:它将一个包含三个元素的数组分配给 x。仅此而已。

第二行

第二行调用传递符号的Object#send方法(请记住,所有以 rubyx​​ 开头的符号都是符号) 、(a ) 和(another )。 现在你只需要看看 send 方法做了什么(正如你所说的你已经完成了):::[]=0Fixnum2Fixnum

调用由符号标识的方法,将任何指定的参数传递给它

这意味着它将调用由标识的方法并将其:[]=传递给它。现在让我们来看看方法。这个方法定义(如果你需要的话可以重载)是:02Array#[]=

class Array
    # ...
    def []=(a, b)
        # ...
    end
end

如果你问我,这个方法是由sendas调用的,x.[]=(0, 2)这很丑陋。这就是为什么 Ruby 定义了一个语法糖版本:x[0] = 2一般来说:

x.[]=(a, b)  -->  x[a] = b

在这种Array情况下,我们还有以下内容:

x.[](a)  -->  x[a]

在这两种情况下,您都可以在特定上下文中自由调用任何对您有意义的版本。

第三行

现在是第三行和最后一行:

x[0] + x.[](1) + x.send(:[],2)

事情变得非常棘手。我们把它分为:

  1. x[0]
  2. x.[](1)
  3. x.send(:[], 2)

第一个非常简单。它返回数组的第一个元素。

第二个是我们之前看到的语法糖,基本上可以转换x[1]返回数组的第二个元素。

第三个用于Object#send调用[]传递2给它的方法。这意味着它调用x.[](2)which意味着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
于 2013-07-20T12:57:18.970 回答
7

send是一种在 ruby​​ 中实现反射调用的方法。因此这一行:

x.send :[]=,0,2

相当于:

x[0] = 2

您是这样阅读的:方法的名称是符号(在您的情况下[]=),然后传入参数 - 0 和 2。

于 2012-10-15T08:48:32.387 回答
2

x[0]+x[1]+x[2]=2+2+3=7 我想这一定是答案

于 2013-07-20T12:18:32.050 回答