【发布时间】:2017-06-11 18:05:45
【问题描述】:
在 Ruby 中,使用错误数量的参数调用 lambda 会导致 ArgumentError:
l = lambda { |a, b| p a: a, b: b }
l.call(1, 2)
# {:a=>1, :b=>2}
l.call(1)
# ArgumentError: wrong number of arguments (given 1, expected 2)
传递一个数组也不起作用:(因为数组只是一个对象,对吧?)
l.call([3, 4])
# ArgumentError: wrong number of arguments (given 1, expected 2)
除非我使用 splat (*) 将数组转换为参数列表,但我没有。
但是 ...如果我通过yield 隐式调用lambda,就会发生意想不到的事情:
def yield_to
yield(1, 2)
yield([3, 4])
end
yield_to(&l)
# {:a=>1, :b=>2}
# {:a=>3, :b=>4} <- array as argument list!?
更令人困惑的是,通过Method#to_proc 派生的 lambda 确实可以按预期工作:
def m(a, b)
p a: a, b: b
end
yield_to(&method(:m))
# {:a=>1, :b=>2}
# ArgumentError: wrong number of arguments (given 1, expected 2)
这是怎么回事?
【问题讨论】:
-
&不仅仅是打电话给#to_proc所以你的最后一个例子不是那么公平。但我认为这里的关键是yield不会调用#call,它会执行一个“bare bone” 块。而#call方法检查参数然后执行块。 -
看起来
yield使用call(arg)或call(*args)的等效项,具体取决于预期的参数数量。但是,很难找到相应的文档。 -
@ndn 如果我通过
prc = method(:m).to_proc检索过程并调用yield_to(&prc),我会得到相同的结果。prc是一个带有两个必需参数的 lambda,就像l。 -
@EricDuminil 那么最后一个例子也不应该引发异常。
-
相关但 IMO 不重复:stackoverflow.com/questions/23945533/…