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



Mr。Daniel Sobral在这里回答说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]

问题是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的类型是给定的(并且必须是,因为它是一个函数参数),所以不会发生与您的初始问题相对应的类型推断。

相关内容

  • 没有找到相关文章

最新更新