以下是取自scala第5章中fp的Stream类型的定义
sealed trait Stream[+A]
case object Empty extends Stream[Nothing]
case class Cons[+A](h: () => A, t: () => Stream[A]) extends Stream[A]
我们可以编写以下方法,返回的无限流
def constant[A](a: A): Stream[A] = {
lazy val x: Stream[A] = Cons(() => a, () => x)
x
}
我不太明白的是,当x被定义为惰性val时,为什么编译器不抛出正向引用扩展到值的定义?
我在这里找到了一个旧帖子:https://www.scala-lang.org/old/node/6502但仍在寻找一个明确的解释。
因为现在,正是由于您链接的帖子(AFAIK(,它是特别允许的:
声明或定义引入的名称的作用域是包含绑定的整个语句序列。然而,块中的前向引用有一个限制:在组成块的语句序列s1…sn中,如果si中的一个简单名称指的是由sj定义的实体,其中j≥i,则对于si和sj之间并包括si和sj的所有sk,
sk不能是变量定义。
如果sk是一个值定义,它必须是惰性的。
我不会详细介绍,也许这对你来说就足够了。。。它的工作原理和递归函数一样。惰性val的行为就像记忆函数。
此外,您也可以使它作为val工作,但它不能是局部变量。看到
class Test {
val a = 5
val x: Stream[Int] = Cons(() => a, () => x)
}
编译得很好。