更新:使用两个构造函数的用法更新了代码,基本上我感到困惑的是,Cons
和 Stream.cons 之间有什么区别
。附:这个例子来自《Scala 函数式编程》一书的第 5 章。
那么谁能向我解释为什么下面的惰性评估没有按预期工作?我的 Scala 工作表的输出是
One
res0: Int = 1
One
res1: Int = 2
One
res2: Int = 3
One
res3: Int = 4
One
res4: Int = 5
One
res5: Int = 6
显然这不是预期的输出,因为由于惰性求值 One
应该只打印一次,而 i
应该只增加一次,但这似乎并不就这样吧。我错过了一些东西,但看不到它,任何新的眼睛介意伸出援手吗?
sealed trait Stream[+A] {
def toList: List[A] = {
@annotation.tailrec
def go(s: Stream[A], acc: List[A]): List[A] = s match {
case Cons(h,t) => go(t(), h() :: acc)
case _ => acc
}
go(this, List()).reverse
}
}
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
object Stream {
def cons[A](hd: => A, tl: => Stream[A]): Stream[A] = {
lazy val head = hd
lazy val tail = tl
Cons(() => head, () => tail)
}
def empty[A]: Stream[A] = Empty
def apply[A](as: A*): Stream[A] =
if (as.isEmpty) empty
else cons(as.head, apply(as.tail: _*))
}
var i = 0
val nonLazy = Cons(
() => { println("One"); i+=1; i },
() => Cons(
() => { println("Two"); i+=2; i },
() => Empty))
nonLazy.h
nonLazy.h
nonLazy.h
var i = 0
val lazy = Stream.cons(
() => { println("One"); i+=1; i },
Stream.cons(
() => { println("Two"); i+=2; i },
Empty)).toList
lazy.head
lazy.head
lazy.head
lazy.head
lazy.head
lazy.head
最佳答案
lazy val head = hd
由于您没有指定head
的类型,因此它将是() => Int
,并且每次获取head时,hd
正在评估,i
不断增加
我认为您想要计算hd
并将值存储在Stream.cons
函数中,因此您需要显式指定类型:
lazy val head: A = hd
tail
变量也是如此。
关于scala - 惰性求值解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33246328/