在尾递归函数中使用Nil作为初始累加器

时间:2014-02-20 03:04:23

标签: scala null accumulator

Mr. Daniel Sobral已回复here Nil fold无法用作Nil的初始累加器。

不能使用scala> xs res9: List[Int] = List(1, 2, 3) scala> xs.foldLeft(Nil)( (acc, elem) => elem.toString :: acc) <console>:9: error: type mismatch; found : List[String] required: scala.collection.immutable.Nil.type xs.foldLeft(Nil)( (acc, elem) => elem.toString :: acc) 作为初始累加器值

List[String]()

但如果我通过scala> xs.foldLeft(List[String]())( (acc, elem) => elem.toString :: acc) res7: List[String] = List(3, 2, 1) ,它就会有用。

Nil

但为什么我可以在下面的尾递归函数中使用scala> def toStringList(as: List[Int]): List[String] = { | def go(bs: List[Int], acc: List[String]): List[String]= bs match { | case Nil => acc | case x :: xs => go(xs, x.toString :: acc) | } | println(as) | go(as, Nil) | } toStringList: (as: List[Int])List[String]

{{1}}

1 个答案:

答案 0 :(得分:2)

问题是Scala使用第一个参数列表启动类型推断。给定def foldLeft[B](z: B)(f: (B, A) => B): B

xs.foldLeft(Nil)(...)

它将B推断为Nil.type(只有一个值的类型:Nil)并使用它来键入 - 检查第二个参数列表,这显然会失败。但是,List[String]()的类型为List[String],因此BList[String],这将与您的f一起使用。另一种解决方法是显式编写类型参数:

xs.foldLeft[List[String]](Nil)(...)

在第二个程序中,给出acc的类型(并且必须是,因为它是一个函数参数),因此不会发生与您的初始问题相对应的类型推断。