foldLeft在Scala中的实现

foldLeft在Scala中的实现,scala,collections,fold,Scala,Collections,Fold,使用可变的var结果实现foldLeft def foldLeft[B](z: B)(op: (B, A) => B): B = { var result = z this foreach (x => result = op(result, x)) result } 我理解递归实现foldLeft是不实际的。现在我想知道是否有可能在没有可变变量的情况下高效地实现foldLeft 能做到吗?如果不能,为什么?尾部递归是你的朋友: def foldLeft[A, B]

使用可变的
var结果实现
foldLeft

def foldLeft[B](z: B)(op: (B, A) => B): B = {
   var result = z
   this foreach (x => result = op(result, x))
   result
}
我理解递归实现
foldLeft
是不实际的。现在我想知道是否有可能在没有可变变量的情况下高效地实现
foldLeft


能做到吗?如果不能,为什么?

尾部递归是你的朋友:

def foldLeft[A, B](xs: Seq[A], z: B)(op: (B, A) => B): B = {
  def f(xs: Seq[A], acc: B): B = xs match {
    case Seq()   => acc
    case x +: xs => f(xs, op(acc, x))
  }
  f(xs, z)
}

顺便说一句,
TraversableOnce
不实现
head
tail
,访问元素的唯一方法是使用
foreach

除非集合是
列表
,否则
toList
操作需要
O(n)
。因此,这是一个低效的解决方案。因此foldLeft仍然是O(n):p,就像sschaef所说的,在
transversableOnce
内部,访问元素的唯一方法是
foreach
,所以当您真的想递归地执行时,您将不得不失去一些效率……因此,这个问题的完整答案是:可以以最有效的方式实现不带可变变量的
foldLeft
,但不能以
TraversableOnce
实现,因为缺少
O(1)
head和tail函数。您可能应该将其添加到您的答案中。使用
toIterator
时,开销不应该更低吗?
def foldLeft[B](z: B)(op: (B, A) => B): B = {
  val thislist = this.toList
  @tailrec
  def myFold(result: B, list: List[A]): B = list match {
    case Nil => result
    case head :: tail => myFold(op(result,head), tail)
  }
  myFold(z, thislist)
}