Scala Stream按需调用(懒惰)与按名称调用

pla*_*pus 6 scala stream

所以我理解,按需调用只是一个按名称调用的memoized版本.在Martin Odersky的课程FP课程中,在7.3课程(懒惰评估)中,他提到如果Streams是使用call-by-name实现的,那么它可能会导致计算复杂性的爆炸.

这种爆炸的例子是什么?

呼叫按姓名:

def cons[T](hd: T, tl: => Stream[T]) = new Stream[T] {
  def head = hd
  def tail = tl
  ...
}
Run Code Online (Sandbox Code Playgroud)

呼叫按需要:

def cons[T](hd: T, tl: => Stream[T]) = new Stream[T] {
  def head = hd
  lazy val tail = tl
  ...
}
Run Code Online (Sandbox Code Playgroud)

0__*_*0__ 2

例如斐波那契数列,通过将前两个元素相加形成后继来实现。如果没有记忆,序列的长度将会线性减慢(和堆栈增长):

scala> lazy val fib: Stream[Int] = Stream.cons(0,
     | Stream.cons(1, fib.zip(fib.tail).map(p => p._1 + p._2)))
fib: Stream[Int] = Stream(0, ?)
Run Code Online (Sandbox Code Playgroud)

从这个博客复制的懒惰示例(-sic-)