运算符 Array#<< 在 shorthand 形式的 reduce 中失败

Operator Array#<< failed in shorthand form of reduce

有众所周知的 shorthand 形式可以将块传递给任何方法,基于 Symbol#to_proc 实现。

而不是:

[1,2,3].reduce(0) { |memo, e| memo + e }
# or
[1,2,3].reduce { |memo, e| memo.+(e) }

有人可能会写:

[1,2,3].reduce &:+

以上是后者“标准符号”的确切“同义词”。


现在让我们有两个数组:

a = [[1,"a"],[2,"b"]]
b = [[3,"c"],[4,"d"]]

同时

b.reduce(a) { |memo, e| memo << e }
# and
b.reduce(a) { |memo, e| memo.<<(e) }

将正确更新 a 数组,与 a.concat(b) 完全一样:

#⇒ [[1,"a"], [2,"b"], [3,"c"], [4,"d"]]

短符号突然引发异常:

b.reduce(a) &:<<
#⇒ TypeError: [[1, "a"], [2, "b"]] is not a symbol

我错过了什么? Ruby 2.1.


P.S. 演员 .

b.reduce(a) &:<<

不会工作,因为它不是有效的方法调用。相反,将符号作为最后一个参数传递:

b.reduce(a, &:<<)
# => [[1, "a"], [2, "b"], [3, "c"], [4, "d"]]

当你打电话时:

[1,2,3].reduce &:+

&:+ 是方法的参数。它实际上等同于:

[1,2,3].reduce(&:+)

如果方法的最后一个参数前面有 &,它被认为是 Proc 对象(SymbolProc 技巧)。然后将其从参数列表中移除,并转换为块,然后该方法关联块。