在scala中做一个懒惰变量

ayv*_*ngo 11 scala lazy-evaluation

Scala不允许创建laze vars,只允许lazy vals.有道理.

但我已经碰到了用例,我希望能有类似的功能.我需要一个懒惰的变量持有者.可以为其分配应该由耗时算法计算的值.但它可能会在以后重新分配给另一个值,我不想再调用第一个值计算.

假设有一些魔术var定义的示例

lazy var value : Int = _
val calc1 : () => Int = ... // some calculation
val calc2 : () => Int = ... // other calculation
value = calc1
value = calc2
val result : Int = value + 1
Run Code Online (Sandbox Code Playgroud)

这段代码应该只调用calc2(),而不是calc1

我知道如何用隐式转换和特殊容器类编写这个容器.我很好奇是否有任何嵌入式scala功能,不需要我编写不必要的代码

Mal*_*off 7

这有效:

var value: () => Int = _
val calc1: () => Int = () => { println("calc1"); 47 }
val calc2: () => Int = () => { println("calc2"); 11 }
value = calc1
value = calc2
var result = value + 1 /* prints "calc2" */

implicit def invokeUnitToInt(f: () => Int): Int = f()
Run Code Online (Sandbox Code Playgroud)

由于它广泛适用,因此隐含了我的担忧,这可能导致意外的应用程序或编译器错误的模糊含义.



另一种解决方案是使用带有setter和getter方法的包装器对象来实现惰性行为:

lazy val calc3 = { println("calc3"); 3 }
lazy val calc4 = { println("calc4"); 4 }

class LazyVar[A] {
  private var f: () => A = _
  def value: A = f() /* getter */
  def value_=(f: => A) = this.f = () => f /* setter */
}

var lv = new LazyVar[Int]
lv.value = calc3
lv.value = calc4
var result = lv.value + 1 /* prints "calc4 */
Run Code Online (Sandbox Code Playgroud)

  • 这不是一个正确的解决方案,因为它没有捕获懒惰的"缓存"性质.即每次评估lv.value时,该函数将被重新执行(在此示例中,它将一次又一次地打印). (2认同)

sen*_*nia 1

var value: () => Int = _
lazy val calc1 = {println("some calculation"); 1}
lazy val calc2 = {println("other calculation"); 2}
value = () => calc1
value = () => calc2

scala> val result : Int = value() + 1
other calculation
result: Int = 3
Run Code Online (Sandbox Code Playgroud)