【问题标题】:How does this code with send :[] work?这个带有 send :[] 的代码是如何工作的?
【发布时间】:2015-09-30 00:29:05
【问题描述】:

以下代码生成的输出为 9。我了解 send 只是调用方法 :[],但对参数的工作原理感到困惑。

 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

第 2 行和第 3 行如何工作?

【问题讨论】:

    标签: ruby methods


    【解决方案1】:

    Object#send 提供了另一种调用方法的方式。

    x.send :[]=,0,4  
    

    就是说,在x上调用[]=方法,并传递参数04,相当于:

    x[0] = 4
    

    send 这个名字是因为在 Ruby 中,方法是通过向对象发送消息来调用的。该消息包含方法的名称,以及该方法可能需要的参数。这个想法来自 SmallTalk。

    【讨论】:

      【解决方案2】:
      x.send(:[]=, 0, 4)
      

      与*相同

      x.[]=(0, 4) 
      

      它的语法糖是

      x[0] = 4
      

      这应该是其他语言所熟悉的。 当然,括号是可选的。

      .send.public_send 变体的优点是调用的方法不必硬编码——它可以来自变量。

      这一切都与 ruby​​ 的面向对象范式一致:对象通过发送消息相互通信,消息触发代码执行。


      *几乎,#send 也会调用私有方法

      【讨论】:

        【解决方案3】:

        第 2 行是

        x.send :[]=,0,4
        

        这基本上是一种奇特的写法:

        x[0] = 4
        

        (虽然调用send 允许您调用私有方法,这是两种语法之间的一个区别。此外,可以想象一个对象可以覆盖send 方法,这会破坏第一种语法。)

        所以第 2 行的效果是将 4 写入数组的第一个位置。

        现在在第 3 行,我们看到我们将三件事相加。以下是我们要添加的内容的列表:

        • x[0] - 第一个元素
        • x.[](1) - 访问元素的另一种语法,它访问第二个元素。这种语法是传统的方法调用,其中方法的名称恰好是[]
        • x.send(:[], 2) - 这显示了 Ruby 的另一个特性,即 send 方法。它访问第三个元素。

        所以结果将是 9,因为第三行添加了数组的第一个、第二个和第三个元素。

        这些示例似乎说明了有关 Ruby 语言设计的一个有趣点。具体来说,数组访问是作为方法调用实现的。写入数组的首选语法是x[0] = 4,读取的首选语法是x[0],因为许多不同语言的程序员都熟悉这种语法。然而,从数组中读取和写入实际上是在底层使用方法调用来实现的,这就是为什么可以使用其他一些看起来更像传统方法调用的语法。

        传统的方法调用如下所示:object.foo(arg1, arg2, arg3, ...)

        上面显示的send 是 Ruby 的一个有用功能,它允许您使用符号指定要调用的方法,而不是强制您输入确切的名称。它还允许您调用私有方法。

        【讨论】:

        • "x.send(:[]=, 0, 4)x[0] = 4 的一种写法,或者"x[0] = 4x.send(:[]=, 0, 4) 的一种方便写法"?
        • "... 这基本上是一种奇特的写法:..."--我会说这是相反的方式。
        猜你喜欢
        • 2010-12-13
        • 2013-04-23
        • 2015-04-09
        • 2013-07-24
        • 2014-03-26
        • 2012-11-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多