List.view 和 LazyList 有什么区别?

What is the difference between List.view and LazyList?

我是 Scala 的新手,我刚刚了解到创建 LazyList 是为了替换 Stream,同时他们将 .view 方法添加到所有集合中。

所以,我想知道为什么 LazyList 添加到 Scala 集合库中,我们什么时候可以做 List.view

我刚刚看了 Scaladoc,似乎唯一的区别是 LazyList 有记忆,而 View 没有。我是对还是错?

Stream 元素是惰性实现的 除了 第一个(头)元素。这被视为一种缺陷。

一个 List 视图被懒惰地重新评估,但据我所知,必须首先完全实现。

def bang :Int = {print("BANG! ");1}

LazyList.fill(4)(bang)  //res0: LazyList[Int] = LazyList(<not computed>)
Stream.fill(3)(bang)    //BANG! res1: Stream[Int] = Stream(1, <not computed>)
List.fill(2)(bang).view //BANG! BANG! res2: SeqView[Int] = SeqView(<not computed>)

在 2.13 中,您不能强制从视图返回到原始集合类型:

scala> case class C(n: Int) { def bump = new C(n+1).tap(i => println(s"bump to $i")) }
defined class C

scala> List(C(42)).map(_.bump)
bump to C(43)
res0: List[C] = List(C(43))

scala> List(C(42)).view.map(_.bump)
res1: scala.collection.SeqView[C] = SeqView(<not computed>)

scala> .force
            ^
       warning: method force in trait View is deprecated (since 2.13.0): Views no longer know about their underlying collection type; .force always returns an IndexedSeq
bump to C(43)
res2: scala.collection.IndexedSeq[C] = Vector(C(43))

scala> LazyList(C(42)).map(_.bump)
res3: scala.collection.immutable.LazyList[C] = LazyList(<not computed>)

scala> .force
bump to C(43)
res4: res3.type = LazyList(C(43))

如果调用者需要选择结果类型,则采用视图并可选择返回严格实现的函数也必须采用 "forcing function",例如 _.toList

我在日常工作中不会做这种事情,但这种行为让我感到惊讶。