给出以下采用一个参数的方法:
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(*[])
。但是,如果我使用非 -empty数组调用它, 的行为与我预期的方式相同:
method(:foo).to_proc.call([1])
# prints [1]
因此它会对参数进行解构,但前提是该参数恰好是一个空数组。只有我打电话给Method#to_proc
。
我对Method
或Proc
的工作方式有何看法,或者这是一个错误?
我正在运行Ruby 1.8.7-p299。我在1.8.6-p399和1.8.7-head中观察到相同的行为。但是,我没有在1.9.1-p378中看到它:当使用空数组调用时,所有三个表单都打印[]
。
答案 0 :(得分:13)
这几乎肯定是一个错误,
我怀疑发生这种情况的原因是Method#call有arity -1(期望C数组的参数),而Proc#call有arity -2(期望Ruby数组的参数)。
在eval.c中还有一个有用的评论,它在Proc#call的定义之上,可以进一步阐明这个问题:
/ * CHECKME:参数检查语义是否正确? * /
也许我们应该将其更改为FIXME:p