2

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()
  }
Som Bhattacharyya
  • 3,972
  • 35
  • 54
  • 1
    After `myExpr = () => expr`, if `myExpr` is ever invoked via `myExpr()`, then `expr` will, at long last, after all this time, finally be evaluated. – jwvh Jul 14 '16 at 09:02
  • 1
    Possible duplicate of [What's the difference between => , ()=>, and Unit=>](http://stackoverflow.com/questions/4543228/whats-the-difference-between-and-unit) – Gabriele Petronella Jul 14 '16 at 09:12

1 Answers1

2
expr: => T

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.

private var myExpr: () => T = _

Indicates that it is a variable of type () => T which means that it takes no arguments and returns T. If you put expr: () => T as function argument it makes an argument of type () => T which, again, means it takes no arguments and returns T, 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:

myExpr = () => 4
myExpr() //evaluates as 4

Whereas calling myExpr() without assigning () => 4 to it would throw java.lang.NullPointerException.

In the coursera course Odersky explaines very well what is a call-by-name evaluation with his def loop: Unit = loop example.

sebszyller
  • 853
  • 4
  • 10
  • i want to understand why is the assignment `myExpr = () => expr` in the update method. Does it mean i accept a by-name parameter `expr` and save it to myExpr as a "() => expr" ? In other words why would i save a by-name parameter as a function ? – Som Bhattacharyya Jul 14 '16 at 08:48
  • Let's simplify the *by-name*. The way it differs from *by-value* is the way it is evaluated. So, `expr: => T` upon access will evaluate to T and will be no different from `expr: T` which will be evaluated upon the function call. `myExpr = () => expr` is in the update method because `expr: => T` is in the constructor and it might be a very long computation that you don't want to evaluate upon instantiation of the object. Nextly, yes, it does mean that you save it to `myExpr` as you said and you want it for the reason mentioned one sentence above. – sebszyller Jul 14 '16 at 09:19