【问题标题】:Why use procs instead of methods?为什么使用过程而不是方法?
【发布时间】:2012-04-03 10:41:55
【问题描述】:

我是编程新手,Ruby 是我第一次真正接触它。我得到了块,但 procs 似乎是一个轻量级的方法/函数概念——为什么要使用它们?为什么不直接使用方法?

感谢您的帮助。

【问题讨论】:

    标签: ruby proc-object


    【解决方案1】:

    Proc 是一段可调用的代码。您可以将其存储在变量中,作为参数传递,否则将其视为first-class value

    为什么不直接使用方法?

    取决于您在这里所说的“方法”是什么意思。

    class Foo
      def bar
        puts "hello"
      end
    end
    
    f = Foo.new
    

    在这段代码中,sn-p 方法bar 的使用非常有限。你可以调用它,就是这样。但是,如果您想存储对它的引用(传递到其他地方并在那里调用它),您可以这样做:

    f = Foo.new
    bar_method = f.method(:bar)
    

    这里的bar_method 非常类似于 lambda(类似于 Proc)。 bar_method 是一等公民,f.bar 不是。

    有关更多信息,请阅读@minitech 提到的the article

    【讨论】:

    • 这并不完全准确。 's'.method(:size) 可以存储在变量中,作为参数传递,或者作为第一类值处理,但它是一种方法,而不是 Proc。
    • 对我来说,这通常更多是关于闭包或需要一段不需要self 的代码(或者self 不是正确的东西)。 Ruby 中的整个 Method/Proc/lambda/block 东西在 IMO 中有点乱。我很难想出一个最终不会成为一本书整章的好答案。
    • @muistooshort:那你应该写一本书并参考它:)
    • 谢谢大家,这有助于我朝着正确的方向思考。
    【解决方案2】:

    调度表设计模式示例


    为什么使用过程而不是方法?

    • 您可能希望在行为变化的情况下动态定义一个 根据参数。
    • 您可能想要获取方法的句柄 因此您可以将其作为数据引用。

    一种常见的设计模式涉及根据运行时值选择要调用的方法或代码块。比如……

    case 1
      when 0
        p :a
      when 1
        p :b
      when 2
        p :c
    end
    

    当有许多选择器并且没有办法将调度机制逐步组合在一起时,这会变得有点笨拙。因此,可以这样做:

    h = [ proc { p :a }, proc { p :b }, proc { p :c } ]
    
    h[1].call
    

    如果您的键不是小整数序列,您也可以使用Hash 而不是Array。尽管笨拙的 case-selector 设计模式在所有语言中都经常出现,但 dispatch-table-of-procs 却很少使用。通常,可以将结果本身存储在ArrayHash 中,然后直接索引它们。但是对于复杂的事情,调用proc 可以提供最大的灵活性。

    当您继续使用 Ruby 时,您会发现这就是 Ruby 有块的原因。块本质上是作为参数传递给另一个方法的方法。这在 Ruby 和 Smalltalk 中很容易做到,以至于它一直被使用。你可以在 C 中做同样的事情,但它太尴尬了,没有任何乐趣,所以只有当代码编写者在与复杂性的拼命战斗中失败时,才会在 C 中看到它。

    【讨论】:

    • 我喜欢这个,但我不会使用数组索引的位置来触发每个 proc,因为在任何类型的大序列中都很难推断出跟踪该顺序。我会将每个 proc 项链接到映射数字的哈希键。
    猜你喜欢
    • 2010-11-23
    • 2018-09-12
    • 2011-08-23
    • 2018-11-03
    • 2011-02-15
    • 1970-01-01
    • 2016-06-22
    • 2011-07-23
    • 2016-06-11
    相关资源
    最近更新 更多