【问题标题】:Ruby method, Proc, and block confusionRuby 方法、Proc 和块混淆
【发布时间】:2009-08-07 17:45:53
【问题描述】:

关于 Ruby 的方法、过程和块,我有几个问题让我觉得很奇怪。与其说是语法或功能,不如说是决策背后的逻辑。

问题 1:

为什么块可以传递给方法(例如每个方法)但不能分配给变量?

我知道你可以在过程中传递它们,即p = Proc.new {...}(使用&p 访问),但是让程序员通过这些方式没有多大意义。

问题 2:

为什么要区分方法和程序?

例如,我可以通过以下两种方式完成定义函数和调用该函数的任务:

def square(x)
    x**2
end

square(3)
=> 9

square = lambda {|x| x**2}
square.call(3)
=> 9

为什么要区分?例如,在 Python 中,以标准方式定义函数和通过 square = lambda x: x**2 完成创建函数并将其分配给 square 的相同任务。

【问题讨论】:

    标签: ruby


    【解决方案1】:

    问题1:块不是对象,它们是句法结构;这就是为什么不能将它们分配给变量的原因。这是为对象保留的特权。

    问题2:方法不是对象,所以它们不能接收消息。相反,procs 和 lambdas 是对象,因此它们不能像方法一样被调用,但必须接收一条消息,告诉它们根据随消息传递的参数返回一个值。

    Procs 和 Lambda 是对象,因此它们可以接收call 消息并被分配给名称。总而言之,它是一个让 procs 和 lambdas 以你觉得奇怪的方式表现的对象。方法和块不是对象,不共享该行为。

    【讨论】:

    • Ruby 声称一切都是对象。块应该是对象以适应它,并且它们可以作为参数传递,因此它们在某些方面肯定像对象一样。
    • 块可以通过创建一个对象来表示它们,一个proc或一个lambda来表现得像对象。没有那个设备,它们就只是句法结构。
    • 有块对象——这就是 lambda {whatever} 的目的。
    • Lambda 是 proc 的一种特殊形式。查看 The Ruby Programming Language 的第 192 页:books.google.com/…
    • 这个解释是有道理的,尽管我不一定看到这些选择的合理性。这些选择仅仅是为了尊重有影响力的语言(即 smalltalk)的约定吗?
    【解决方案2】:

    至少在某种程度上,方法对象:

    class ABC
      def some_method
      end
    end
    ABC.instance_method(:some_method) #=> #<UnboundMethod: ABC#some_method>
    

    除此之外,还有一个内置类:Method,记录在 here

    另请参阅:http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Method_Calls

    偶然&lt;bseg&gt;,它似乎确实证明了一切都是对象的事情。在这种特殊情况下,它似乎需要更多的挖掘才能看到。

    (我真的必须努力更好地理解这一点:我开始认为这是获得更深入理解的基础。)

    【讨论】:

    • 方法似乎从Proc 的实例中获取了它们的对象性。在Methodri 文档中,解释中没有使用“方法”一词,但使用了“过程”。这两个类接收相同的消息,但不同之处在于它们是如何被调用的,事实上方法是在另一个对象的命名空间中定义的,其中 procs 需要接收callmethod 才能被调用并存在(持久化,如我之前说过)独立于其他对象。
    • 啊,另一个区别...Method 没有收到new 消息,而Proc 收到了。如果方法是对象,那么它们就不是完整意义上的对象(“完整”意味着具有我们习惯于在对象中看到的所有特征)。
    • 该维基书链接很有帮助。谢谢。
    • 这个答案值得更多的支持。接受的答案无助于混淆,这使它正确。
    【解决方案3】:

    方法就是方法——也就是说,它们是对象响应消息时可以采取的动作。它们不是函数。

    块是闭包——它们是在封闭范围内关闭的函数。它们在概念上并不“属于”给定对象。

    在某些语言中,方法仅仅是作为对象成员的函数,但 Ruby 不以这种方式看待它们。将方法与其拥有的对象分离更像是手术,而不是简单的分配。 Ruby 的面向对象模型来自现代 OO 的鼻祖 Smalltalk

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多