我理解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定义为字段,我发现它工作正常。我也注意到post关于val的实现。结论是val在方法或字段或REPL中具有不同的实现。这真的令人困惑。
答案 0 :(得分:2)
如果您要定义函数,那么替换模型适用于递归,但除非它是惰性的,否则您无法根据自身定义变量。计算右侧所需的所有信息必须可用于分配,因此为了递归地定义变量需要一点懒惰。
You probably don't really want to do this,但只是为了表明它适用于函数:
scala> def r = { def x:Stream[Int] = 1#::( x map (_+1) ); x }
r: Stream[Int]
scala> r take 3 foreach println
1
2
3