为什么在Scala列表的inits方法中需要中间newBuilder

为什么在Scala列表的inits方法中需要中间newBuilder,scala,Scala,Scala为Lists定义了inits方法,该方法执行以下操作: List(1, 2, 3).inits.toList // List(List(1, 2, 3), List(1, 2), List(1), List()) 其实施方式如下: def inits: Iterator[Repr] = iterateUntilEmpty(_.init) private def iterateUntilEmpty(f: Traversable[A @uV] => Traversable[A

Scala为
List
s定义了
inits
方法,该方法执行以下操作:

List(1, 2, 3).inits.toList  // List(List(1, 2, 3), List(1, 2), List(1), List())
其实施方式如下:

def inits: Iterator[Repr] = iterateUntilEmpty(_.init)

private def iterateUntilEmpty(f: Traversable[A @uV] => Traversable[A @uV]): Iterator[Repr] = {
  val it = Iterator.iterate(thisCollection)(f) takeWhile (x => !x.isEmpty)
  it ++ Iterator(Nil) map (x => (newBuilder ++= x).result)
}
我突然想出了一个不太通用的版本(只是为了玩):

但在我看来,我们可以不使用
ListBuffer
部分:

val L = List(1,2,3)
val it = Iterator.iterate(L)(_.init) takeWhile (x => !x.isEmpty)
it ++ Iterator(Nil) toList
// List(List(1, 2, 3), List(1, 2), List(1), List())
结果似乎是一样的

那么为什么库实现使用
newBuilder


它对性能有何影响?

希望Rex Kerr@Rex Kerr能够启动某种长期运行的工作,并检查是否存在问题,但在此之前,您会问为什么列表不专门化
TraversableLike.inits

我认为两个答案是,为每个具体集合专门化是一个维护问题,重写该方法与JVM编译它的策略相竞争

我想我在源代码中读到,JVM将在性能受到影响之前容忍两次这样的重写调度。我不是专家,但直觉是假设一种方法是有效的最终方法更有效

但是请稍候,您的
.toList
.map(u.toList)
不同

您的问题归结为,既然您从迭代器获得列表,为什么不完全取消List的构建器呢

好吧,也许它不适合其他类型:

scala> val is = (1 to 10).to[Vector]
is: Vector[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> val is2 = Iterator.iterate(is)(_.init) takeWhile (x => !x.isEmpty)
is2: Iterator[Vector[Int]] = non-empty iterator

scala> is2 ++ Iterator(Nil)
res9: Iterator[scala.collection.immutable.Seq[Int] with scala.collection.AbstractSeq[Int] with Serializable] = non-empty iterator
scala> val is = (1 to 10).to[Vector]
is: Vector[Int] = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

scala> val is2 = Iterator.iterate(is)(_.init) takeWhile (x => !x.isEmpty)
is2: Iterator[Vector[Int]] = non-empty iterator

scala> is2 ++ Iterator(Nil)
res9: Iterator[scala.collection.immutable.Seq[Int] with scala.collection.AbstractSeq[Int] with Serializable] = non-empty iterator