我很好奇 Ruby 中的块中是否有尾随逗号。
例如:
[[1, 2], [3, 4]].collect { |x, | x }
# returns [1, 3]
Run Code Online (Sandbox Code Playgroud)
就好像第一个参数后面有一个可选参数。
然而:
(proc { |x, | x }).arity
# returns 1
Run Code Online (Sandbox Code Playgroud)
如果 arity 为 1,则数组不应在 X 上分解。
检查(proc { |x, | x }).parameters没有提示这是任何“秘密”第二个参数。
是否有内省的方法来区分proc { |x, | }与 不同proc { |x| }?
我了解分解等的基础知识,并且我可以看到尾随逗号有效地在 |x, | 中创建了一个“秘密”参数。和|x,_| 工作相同。
但令我惊讶的是,除了进入 AST 之外,没有任何内省的方法可以发现尾随逗号的存在。这真是令人惊讶。
在大多数情况下,参数列表中的尾随逗号不起作用。然而,在您刚才列出的具体情况下,这一点很重要。
Ruby 有两种类型的过程对象:严格的和非严格的。使用{ ... }或 使用proc函数创建的块是非严格的,而->lambda 是严格的。同样,def方法总是严格的。
必须使用正确数量的参数调用严格函数。非严格函数将接受任意数量的参数,并根据需要填充/截断参数列表。非严格函数在数组解构方面也有特殊行为。如果非严格函数 (a) 声明为采用多个参数,并且 (b) 只给出一个参数(即数组),则该数组将被解构并被视为多个参数。这就是为什么大多数函数都Enumerable可以在 上“工作” Hash,尽管Hash函数似乎带有两个参数。当你写的时候
my_hash.map { |k, v| ... }
Run Code Online (Sandbox Code Playgroud)
on正在传递一个 array ,但该块足够聪明,可以对其进行解构map。但是,如果该块被声明为只接受一个参数,则它不会解构。尾随的逗号指示 Ruby 解构参数,即使只有一个声明的参数。Enumerable[k, v]
[[1, 2], [3, 4]].collect { |x| x }
Run Code Online (Sandbox Code Playgroud)
这里有一个声明的参数,因此不会发生解构。这样就返回了[[1, 2], [3, 4]]。
[[1, 2], [3, 4]].collect { |x,| x }
Run Code Online (Sandbox Code Playgroud)
后面的逗号表示“无论如何都要解构”。因此该块将被调用1,然后3。“无关的”参数2和4被删除,因为块是非严格的。该代码块的结果是[1, 3]