【问题标题】:Operator Array#<< failed in shorthand form of reduce运算符 Array#<< 以 reduce 的简写形式失败
【发布时间】:2015-11-21 09:03:34
【问题描述】:

基于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

我错过了什么?红宝石 2.1。


P.S.this question铸造。

【问题讨论】:

    标签: arrays ruby reduce


    【解决方案1】:
    b.reduce(a) &:<<
    

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

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

    当你打电话时:

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

    &amp;:+ 是该方法的参数。它实际上相当于:

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

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

    【讨论】:

    • 我将在这里为未来的访问者添加一个附录:TypeError ... is not a symbol 被抛出,因为 Enumerable#reduce 在没有块的情况下被调用,仍然接受 后者 Symbol 参数,将其转换为 proc 并用作块。也就是说,上面的 & 符号是多余的:b.reduce a, :&lt;&lt; 可以解决问题。
    猜你喜欢
    • 2014-07-13
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 2021-03-22
    • 2021-02-08
    • 1970-01-01
    • 2013-06-29
    • 1970-01-01
    相关资源
    最近更新 更多