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.

Était-ce utile?

La 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top