Question

I understand the basic of diff between val and lazy val . but while I run across this example, I 'm confused.

The following code is right one. It is a recursion on stream type lazy value.

def recursive(): {
     lazy val recurseValue: Stream[Int] = 1 #:: recurseValue.map(_+1) 
     recurseValue
}

If I change lazy val to val. It reports error.

def recursive(): {
     //error forward reference failed.
     val recurseValue: Stream[Int] = 1 #:: recurseValue.map(func) 
     recurseValue
}

My trace of thought in 2th example by substitution model/evaluation strategy is :

the right hand sight of #:: is call by name with that the value shall be of the form :

1 #:: ?,

and if 2th element being accessed afterward, it refer to current recurseValue value and rewriting it to :

1 :: ((1 #:: ?) map func) = 1 :: (func(1) #:: (? map func))

.... and so on and so on such that the compiler should success.

I don't see any error when I rewriting it ,is there somthing wrong?

EDIT: CONCLUSION:I found it work fine if the val defined as a field. And I also noticed this post about implement of val. The conclusion is that the val has different implementation in method or field or REPL. That's confusing really.

Was it helpful?

Solution

That substitution model works for recursion if you are defining functions, but you can't define a variable in terms of itself unless it is lazy. All of the info needed to compute the right-hand side must be available for the assignment to take place, so a bit of laziness is required in order to recursively define a variable.

You probably don't really want to do this, but just to show that it works for functions:

scala> def r = { def x:Stream[Int] = 1#::( x map (_+1) ); x }
r: Stream[Int] 
scala> r take 3 foreach println
1
2
3
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top