我刚刚发现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))
现在我只是好奇。 能否请您解释一下为什么它的实施方式如此不同?
答案 0 :(得分:5)
override
中的List
似乎会覆盖foldRight
中的LinearSeqOptimized
。 LinearSeqOptimized
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
按钮,因此您可以随时查看更改内容,由谁以及为什么更改。