Ruby 1.9 中更自然的 Proc 调用方式

Posted

技术标签:

【中文标题】Ruby 1.9 中更自然的 Proc 调用方式【英文标题】:More natural way of Proc calling in Ruby 1.9 【发布时间】:2012-09-24 07:49:19 【问题描述】:

我们知道,在 Ruby 1.9 中有几种 Proc 调用方式

 f =->n [:hello, n]
 p f[:ruby]       # => [:hello, :ruby]
 p f.call(:ruby)  # => [:hello, :ruby]
 p f.(:ruby)      # => [:hello, :ruby]
 p f === :ruby    # => [:hello, :ruby]

我很好奇,调用 Proc 的更“自然”方式是什么? “自然”可能意味着更多类似计算机科学的方式。

【问题讨论】:

我会选择选项 2。这似乎很自然。其余的看起来很奇怪。 【参考方案1】:

第二个选项是迄今为止最常用的。

p f.call(:ruby)  # => [:hello, :ruby]

它使它更类似于标准方法。此外,一些库在验证参数检查 #call 方法的可用性时实际上依赖于鸭子类型。在这种情况下,使用 #call 可确保您可以提供响应 #call 的 lambda 或任何其他对象(包括类)。

Rack 中间件是这种约定的一个很好的例子。基本中间件可以是 lambda,也可以使用类提供更复杂的逻辑。

【讨论】:

+1 用于鸭子打字部分——这很重要。在我自己的很多代码中,我使用.responds_to(:call),以便人们可以传递MethodProc 或lambda(或任何其他带有call 方法的东西)。 是的,已修复。我数了第一行。 :P 所有这些也适用于f.(:ruby),因为这只是f.call(:ruby) 的语法糖。【参考方案2】:

我总是使用选项 3。考虑到能够在没有括号的情况下调用方法的语法歧义,这是最接近实际方法调用语法的方法。

【讨论】:

【参考方案3】:

我在Rack源代码中看到了第一种方式。让我困惑了很久。它选自 lib/rack/builder.rb版本:1.6.0.alpha

module Rack
  class Builder
    ...

    def to_app
      app = @map ? generate_map(@run, @map) : @run
      fail "missing run or map statement" unless app

      # This is the first option calling a proc
      # @use is a array of procs (rack middleware)
      @use.reverse.inject(app)  |a,e| e[a] 
    end

    ...
  end
end

【讨论】:

以上是关于Ruby 1.9 中更自然的 Proc 调用方式的主要内容,如果未能解决你的问题,请参考以下文章

Ruby 1.8 和 Ruby 1.9 有啥区别

Ruby 2.1 与 Ruby 2.0 或 1.9 相比,内存使用量增加

如何使用 ruby​​ 1.9 转换字符编码

ruby 1.9:UTF-8 中的无效字节序列

在 os x 上使 ruby​​ 1.9 默认 [重复]

Ruby 1.9不会杀死Python