I am working through a coursera example of Signal and cannot make sense of this syntax,
class Signal[T](expr: => T) {
import Signal._
private var myExpr: () => T = _
private var myValue: T = _
private var observers: Set[Signal[_]] = Set()
private var observed: List[Signal[_]] = Nil
update(expr)
The update method is written as
protected def update(expr: => T): Unit = {
myExpr = () => expr
computeValue()
}
I can understand that expr is being passed by name so is evaluated only when called.
But what i cannot get my head around is why is the myExpr represented as () => T ?
Also why is the assignment written as myExpr = () => expr . From what i understand () => expr denotes a Function0 that returns expr.
I think my understanding of byname is wrong. Can someone please elaborate on this ?
Or can we rewrite the above syntax as follows,
class Signal[T](expr: () => T) {
import Signal._
private var myExpr: () => T = _
private var myValue: T = _
private var observers: Set[Signal[_]] = Set()
private var observed: List[Signal[_]] = Nil
update(expr)
And the update method as ,
protected def update(expr: () => T): Unit = {
myExpr = expr
computeValue()
}
as function argument stands for call-by-name that is not only delayed evaluation (aka lazy) but also that it is evaluated each time it is accessed.
Indicates that it is a variable of type
() => Twhich means that it takes no arguments and returnsT. If you putexpr: () => Tas function argument it makes an argument of type() => Twhich, again, means it takes no arguments and returnsT, which is NOT a call-by-name. These two things are slightly confusing because of syntax similarities but are quite different.You could use it like this:
Whereas calling
myExpr()without assigning() => 4to it would throwjava.lang.NullPointerException.In the coursera course Odersky explaines very well what is a call-by-name evaluation with his
def loop: Unit = loopexample.