这是 Method#to_proc 中的一个错误吗?(Ruby 1.8.7)

13

给定以下接受一个参数的方法:

def foo(arg); p arg; end

我可以使用一个空数组来调用它:

foo([])
# prints []

我还可以将它保存为一个Method对象,并使用一个空数组调用该方法,得到相同的结果:

method(:foo).call([])
# prints []

然而,如果我将Method对象转换为Proc并使用空数组调用,我会得到一个ArgumentError

method(:foo).to_proc.call([])
# ArgumentError: wrong number of arguments (0 for 1)
#   from (irb):4:in `foo'
#   from (irb):4:in `to_proc'
#   from (irb):10:in `call'

我本以为它会像前两种情况一样表现。但实际上,它似乎表现得就像我写了foo(*[])一样。然而,如果我使用一个空的数组来调用它,它会表现出我所期望的行为:

method(:foo).to_proc.call([1])
# prints [1]

如果参数是一个空数组,它将解构该参数,但仅在调用 Method#to_proc 时才解构。

我是否对 MethodProc 的工作方式存在误解,或者这是一个 bug?

我正在运行 Ruby 1.8.7-p299。我观察到在 1.8.6-p399 和 1.8.7-head 中都有相同的行为。然而,在 1.9.1-p378 中,当使用空数组调用这三种形式时,它们都打印出 []


4
通常情况下,当有人认为他们在语言本身中发现了一个漏洞时,我会持怀疑态度,但考虑到它在1.9中按预期工作,我找不到其他解释这种行为的方法。希望更有见识的人能够启迪我们,因为这让我很好奇。 - Jimmy
1
我并不总是在语言本身中找到 bug,但当我发现时,我使用的是 Ruby。 - Josh Lee
1个回答

13

这几乎肯定是一个 bug,

我怀疑发生这种情况的原因是 Method#call 的 arity 为 -1(期望参数为 C 数组),而 Proc#call 的 arity 为 -2(期望参数为 Ruby 数组)。

在 Proc#call 的定义之前,eval.c 中还有一条有用的注释,可能会进一步说明问题:

/* CHECKME: are the argument checking semantics correct? */

也许我们应该把这个注释改成 FIXME :p


4
Ruby 1.9 版本已经修复了这个问题,所以我认为这是一个 bug :) - sethvargo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接