12

给定以下模块:

module Foo
  def self.call
    'foo'
  end
end

我当然希望以下工作:

puts Foo.call  # outputs "foo"

但是,我没想到这会起作用:

puts Foo.()    # outputs "foo"

显然,当方法名称被省略时,Ruby 假定我想调用该call方法。这是在哪里记录的,为什么它会这样?

4

2 回答 2

11

Proc#call

调用块,使用接近方法调用语义的东西将块的参数设置为 params 中的值。如果将多个值传递给只需要一个值的 proc,则生成警告(以前这会默默地将参数转换为数组)。请注意 prc.() 使用给定的参数调用 prc.call() 。这是隐藏“调用”的语法糖。

我做了一些研究,发现方法#()是该方法的语法糖#call..看下面的错误:

module Foo
  def self.bar
    12
  end
end
Foo.()
#undefined method `call' for Foo:Module (NoMethodError)

由于 OP#call在模块Foo类中定义了该方法,Foo#call因此尝试调用Foo.().

这里还有一些例子:

"ab".method(:size).() # => 2
"ab".method(:size).call # => 2
"ab".() # undefined method `call' for "ab":String (NoMethodError)

在这里查看Matz所说的因此与 1.9 中引入的 object.() 语法妥协......

于 2013-10-04T20:07:17.450 回答
0

显然,正如 Arup 所说,这是不久前引入的语法糖,可能是为了让Proc对象更易于使用。(您不必显式调用它们,但可以这样做prc.())。

我还得出结论,这绝对是 Ruby 1.9+ 的一个特性。如果我将 JRuby 切换到 1.8 模式,我会得到这个:

SyntaxError: spam.rb:12: syntax error, unexpected tLPAREN2

所以,在 Ruby 1.9 的变更日志中的某个地方,如果有人真的想从洞穴中挖掘它,它可能会被发现...... :)

于 2013-10-04T20:17:32.883 回答