我了解val
和lazy val
之间差异的基本原理。但是当我看到这个例子时,我感到困惑。
下面的代码是正确的。它是对流类型惰性值的递归。
def recursive(): {
lazy val recurseValue: Stream[Int] = 1 #:: recurseValue.map(_+1)
recurseValue
}
如果我将lazy val
更改为val
。它报告错误。
def recursive(): {
//error forward reference failed.
val recurseValue: Stream[Int] = 1 #:: recurseValue.map(func)
recurseValue
}
我在第二个例子中通过替代模型/评估策略的思路是:
#:的右侧视线按名称调用,其值应为:
1 #:: ?
,
如果第2个元素随后被访问,则引用当前recurseValue
值并将其重写为:
1 :: ((1 #:: ?) map func) =
1 :: (func(1) #:: (? map func))
等等,使得编译器应该成功。
我重写时没有看到任何错误,是不是出了什么问题?
编辑:结论:我发现如果val定义为一个域,它就可以工作。我还注意到了这篇关于val实现的帖子。结论是val在方法、字段或REPL上有不同的实现。这真是令人困惑。
如果您定义函数,则该替换模型适用于递归,但您不能根据变量本身来定义它,除非它是惰性的。计算右侧所需的所有信息都必须可用于进行赋值,因此需要一点惰性才能递归定义变量。
你可能并不真的想这么做,只是为了证明它适用于函数:
scala> def r = { def x:Stream[Int] = 1#::( x map (_+1) ); x }
r: Stream[Int]
scala> r take 3 foreach println
1
2
3