ruby中关于各种类似函数的构造的参数数量以及如何调用它们的规则是什么?
例如,我注意到当有多个参数的块被传递给一个数组参数时,它会被扩展,而这似乎不适用于方法。我经常在hash对象的可枚举模块方法中看到这一点。

{a: 5}.map{|x| x} # [[:a, 5]]
{a: 5}.map{|k, v| [k, v]} # [[:a, 5]]
[[:a, 5]].map{|x| x} # [[:a, 5]]
[[:a, 5]].map{|k, v| [k, v]} # [[:a, 5]]

proc1 = Proc.new{|x| x}
proc1.call 5 # 5
proc1.call 5, 6 # 5
proc1.call [5, 6] # [5, 6]

proc2 = Proc.new{|k, v| [k, v]}
proc2.call 5 # [5, nil]
proc2.call 5, 6 # [5, 6]
proc2.call [5, 6] # [5, 6], not [[5, 6], nil]

def f(k, v); [k, v] end
f 5 # ArgumentError
f 5, 6 # [5, 6]
f [5, 6] # ArgumentError

def g(*vargs); vargs end
g 5 # [5]
g 5, 6 # [5, 6]
g [5, 6] # [[5, 6]]

但是Proc.call的文档似乎没有提到这一点。
还有一些lambda的方法稍有不同,proc使用的是&:name,可能还有其他一些方法。我也不完全确定Proc.new{|x| x}.call是否与yield中的method_that_takes_a_block{|x| x}完全相同。

最佳答案

这背后的原因是多变量赋值和自动splat
以proc2为例(附带一个有趣的用例):

proc2 = Proc.new{|k, v| [k, v]}
proc2.call 5 # [5, nil]
proc2.call 5, 6 # [5, 6]
proc2.call [5, 6] # [5, 6], not [[5, 6], nil]
proc2.call [5, 6, 7] # [5, 6]

使用ruby,您可以进行多变量赋值:
k, v= 5 # => k=5, v=nil
k, v= 5, 6 # => k=5, v=6
k, v= 5, 6, 7 # => k=5, v=6, 7 is not assigned

还可以使用splat运算符展开数组:
k, v= *[5, 6] # => k=5, v=6

还可以使用splat运算符将多个变量打包到一个数组中:
k, *v= *[5, 6, 7] # => k=5, v=[6, 7]

Ruby可以在适当的时候自动splat:
k, v= [5, 6] # => k=5, v=6
k, v= [5, 6, 7] # => k=5, v=6, 7 is not assigned

据我所知,auto splat只适用于变量和Proc参数赋值

09-25 16:48