Scala:为什么我应该将别名参数保存为 Function0

Scala : Why should i save a by-name parameter as a Function0

我正在学习 Signal 的课程示例,但无法理解这种语法,

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)

更新方法写成

    protected def update(expr: => T): Unit = {
    myExpr = () => expr
    computeValue()
  }

我可以理解 expr 是按名称传递的,因此仅在调用时才进行评估。 但是我无法理解的是为什么 myExpr 表示为 () => T ? 还有为什么作业写成 myExpr = () => expr 。据我了解,() => expr 表示 returns expr 的 Function0。 我认为我对 byname 的理解是错误的。有人可以详细说明一下吗?

或者我们可以重写上面的语法如下,

  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)

更新方法为,

 protected def update(expr: () => T): Unit = {
    myExpr = expr
    computeValue()
  }
expr: => T

as function argument 代表 call-by-name 这不仅是延迟求值(又名惰性),而且每次访问时都会求值。

private var myExpr: () => T = _

表示它是一个() => T类型的变量,这意味着它不带参数和returns T。如果你把 expr: () => T 作为函数参数,它会生成一个类型为 () => T 的参数,这再次意味着它没有参数,并且 returns T 不是 [=32] =]按名称调用。 由于语法相似,这两件事有点令人困惑,但完全不同。

你可以这样使用它:

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

而调用 myExpr() 而未将 () => 4 分配给它会抛出 java.lang.NullPointerException.

在 coursera 课程中,Odersky 用他的 def loop: Unit = loop 示例很好地解释了什么是 call-by-name 评估。