【发布时间】:2023-03-19 05:18:01
【问题描述】:
a_proc = Proc.new {|a,b,*c| p c; c.collect {|i| i*b }}
puts a_proc[2,2,4,3]
根据https://ruby-doc.org/core-2.2.0/Proc.html,上面的代码非常直观,a_proc[2,2,4,3] 只是 a_proc.call(2,2,4, 3)隐藏“通话”
但以下(效果很好)让我很困惑
a=[2,2,4,3]
puts a_proc.call(a)
puts a_proc.call(*a)
这似乎与普通的函数调用有很大不同,因为它不检查传入的数字参数。
但是,正如预期的那样,如果同样使用参数,方法调用语义会引发错误
def foo(a,b,*c)
c.collect{|i| i*b}
end
foo([1,2,3,4]) #`block in <main>': wrong number of arguments (given 1, expected 2+) (ArgumentError)
foo(*[1,2,3,4]) #works as expected
我不认为这种不一致是设计故障,因此我们将不胜感激任何对此的见解。
【问题讨论】:
-
不确定设计方面为什么事情是这样的,或者 ruby 如何处理 proc 参数,但请查看
lambda?的文档,其中解释了 procs 的一些技巧(额外参数被忽略,缺少的参数是nil,数组被扩展,等等) -
感谢您提出一个有趣的问题。这与 SO 上的常规做法大相径庭。
-
将
p c更改为puts "a=#{a}, b=#{b}, c=#{c]"并使用一系列参数调用 proc。然后将proc的参数更改为|a,*b,c|(并相应地更改主体),然后再次使用不同的参数调用proc,依此类推。您很快就能回答自己的问题。通常,如果您,人类,看不到分配块变量的逻辑和独特的方式(例如,call(1,2,3,4,5)和|*a,b,*c|),Ruby 也不会,所以她会引发异常;如果你看到一个且只有一个逻辑分配,Ruby 会同意。
标签: ruby arguments proc argument-unpacking