Scala:列表中的不同foldRight实现

时间:2018-03-09 22:25:25

标签: scala

我刚刚发现scala(我在2.12上)为不可变列表 mutable提供了完全不同的 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))

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

1 个答案:

答案 0 :(得分:5)

override中的List似乎会覆盖foldRight中的LinearSeqOptimizedLinearSeqOptimized

中的实施
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按钮,因此您可以随时查看更改内容,由谁以及为什么更改。