懒惰的val v.s.用于Scala中的递归流的val

时间:2014-04-17 01:22:02

标签: scala recursion stream functional-programming lazy-evaluation

我理解vallazy 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中具有不同的实现。这真的令人困惑。

1 个答案:

答案 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