【问题标题】:Scala: different foldRight implementations in listScala:列表中的不同 foldRight 实现
【发布时间】:2018-03-10 06:54:44
【问题描述】:

我刚刚发现 scala(我在 2.12 上)为 不可变列表可变列表 提供了完全不同的 foldRight 实现>.

不可变列表(List.scala):

override def foldRight[B](z: B)(op: (A, B) => B): B =
    reverse.foldLeft(z)((right, left) => op(left, right))

可变列表(LinearSeqOptimized.scala):

  def foldRight[B](z: B)(@deprecatedName('f) op: (A, B) => B): B =
    if (this.isEmpty) z
    else op(head, tail.foldRight(z)(op))

现在我只是好奇。 你能解释一下为什么它的实现方式如此不同吗?

【问题讨论】:

    标签: scala


    【解决方案1】:

    List 中的override 似乎覆盖了LinearSeqOptimized 中的foldRightLinearSeqOptimized中的实现

    def foldRight[B](z: B)(@deprecatedName('f) op: (A, B) => B): B =
      if (this.isEmpty) z
      else op(head, tail.foldRight(z)(op))
    

    看起来与 foldRight 的规范定义完全一样,是您的普通理论书中的变态。然而,正如在SI-2818 中所注意到的,这个实现不是堆栈安全的(对于长列表抛出意外的StackOverflowError)。因此,它被this commit 中的堆栈安全reverse.foldLeft 取代。 foldLeft 是堆栈安全的,因为它是由 while 循环实现的:

    def foldLeft[B](z: B)(@deprecatedName('f) op: (B, A) => B): B = {
      var acc = z
      var these = this
      while (!these.isEmpty) {
        acc = op(acc, these.head)
        these = these.tail
      }
      acc
    }
    

    这有望解释为什么它在 List 中被覆盖。它没有解释为什么它没有在其他类中被覆盖。我想这仅仅是因为可变数据结构的使用频率较低而且无论如何都完全不同(通常在构造不可变数据结构期间作为缓冲区和累加器)。

    提示:Github 上每个文件的右上角都有一个blame 按钮,因此您可以随时跟踪更改的时间、更改的人员和原因。

    【讨论】:

    • 这很有帮助!谢谢!
    • @Normal 我认为,从长远来看,git blame 的提示比答案本身更有用。感谢您的提问,我之前从未关注过@deprecatedName 注释:]
    • 我完全同意)感谢您的提示。
    猜你喜欢
    • 1970-01-01
    • 2016-11-05
    • 2013-06-12
    • 2012-03-25
    • 2018-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    相关资源
    最近更新 更多