我正在研究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
表示返回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()
}
答案 0 :(得分:2)
expr: => T
因为函数参数代表 call-by-name ,它不仅是延迟评估(也称为懒惰),而且每次访问时都会对其进行评估。
private var myExpr: () => T = _
表示它是() => T
类型的变量,这意味着它不接受任何参数并返回T
。如果你将expr: () => T
作为函数参数,它会创建一个() => T
类型的参数,这再次表示它不接受任何参数并返回T
,这不是 call-by-名称的。
由于语法的相似性,这两件事情略有混淆,但却完全不同。
您可以像这样使用它:
myExpr = () => 4
myExpr() //evaluates as 4
调用myExpr()
而不指定() => 4
会导致java.lang.NullPointerException
。
在课程中,Odersky用他的def loop: Unit = loop
示例非常清楚地解释了什么是按姓名调用评估。