在Ruby中发送方法

Xit*_*d13 44 ruby

我刚刚读到了sendRuby中的内容,在查看此代码时我仍然感到困惑(它来自测验但是过去截止日期)

x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)
Run Code Online (Sandbox Code Playgroud)

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

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

我发现了发送的内容,但我仍然有点困惑,并且对这个代码整体感到很困惑.

Chr*_*ald 57

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

使用send允许您使用任意参数将任意"消息"(方法调用)传递给对象.

x.send :sort例如,您可以调用将"sort"消息发送到数组.但是,Sort不需要任何参数,因此我们不必向其传递任何额外的参数.

x#[]=另一方面,接受两个论点.它的方法可以被认为是这样的:

def []=(index, value)
  self.set_value_at_index(index, value)
end
Run Code Online (Sandbox Code Playgroud)

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

  • @ Xitcod13因为:[] =也是send的参数:`send(:[] =,0,2)` (10认同)
  • 顺便说一句,它非常整洁但令人困惑。:P (2认同)

Eur*_*eka 24

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

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

你的第三行也是如此:a[0]Ruby中的语法糖x.[](0).

以下代码比您的示例更简单:

x = [1, 2, 3]
x[0] = 2
x[0] + x[1] + x[2]
Run Code Online (Sandbox Code Playgroud)


Sho*_*hoe 21

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

x = [1,2,3]
x.send :[]=,0,2
x[0] + x.[](1) + x.send(:[],2)
Run Code Online (Sandbox Code Playgroud)

第一行

第一行很清楚:它为x分配了三个元素的数组.这就是它.

第二行

第二行调用传递符号的Object#send方法x(请记住,:以ruby 开头的所有内容都是符号):[]=,0(a Fixnum)和2(另一个Fixnum).
现在你只需要看看send方法的作用(正如你所说的那样):

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

这意味着它将调用由所标识的方法:[]=和通过02给它.现在让我们来看看这个Array#[]=方法.此方法定义(如果需要,可以由您重载)是:

class Array
    # ...
    def []=(a, b)
        # ...
    end
end
Run Code Online (Sandbox Code Playgroud)

这种方法是通过所谓sendx.[]=(0, 2)如果你问我,这是相当难看.这就是为什么Ruby定义了一个语法糖版本:x[0] = 2一般来说:

x.[]=(a, b)  -->  x[a] = b
Run Code Online (Sandbox Code Playgroud)

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

x.[](a)  -->  x[a]
Run Code Online (Sandbox Code Playgroud)

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

第三行

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

x[0] + x.[](1) + x.send(:[],2)
Run Code Online (Sandbox Code Playgroud)

事情变得非常棘手.我们把它分成:

  1. x[0]
  2. x.[](1)
  3. 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)
Run Code Online (Sandbox Code Playgroud)

可以转换为:

x.send(:[]=, a, b)  -->  x.[]=(a, b)
x.send(:[], a)  -->  x.[](a)
x.[]=(a, b)  -->  x[a] = b
x.[](a)  -->  x[a]
Run Code Online (Sandbox Code Playgroud)

至:

x = [1,2,3]
x[0] = 2
x[0] + x[1] + x[2]
Run Code Online (Sandbox Code Playgroud)

可以减少到:

2 + 2 + 3
Run Code Online (Sandbox Code Playgroud)

这导致:

7
Run Code Online (Sandbox Code Playgroud)


Bor*_*jev 7

send是一种在ruby中实现反射调用的方法.这样一行:

x.send :[]=,0,2
Run Code Online (Sandbox Code Playgroud)

相当于:

x[0] = 2
Run Code Online (Sandbox Code Playgroud)

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