Lazy Val - 如何重置值?
Lazy Val - How to reset value?
我可能想使用一种昂贵的方法,return结果取决于副作用。例如,取决于一天/一周的时间和 Monte Carlo 量子时间动力学模拟。因为它很贵而且我可能不需要它,所以我会使用 Scalas lazy val
lazy val maybeUnusedValue = getDayOfWeek
现在 12 个小时过去了,我的程序仍然 运行。我想重新计算,因为我的一天可能在此期间发生了变化。
是否有一种简单的方法可以强制 Scala return maybeUnusedValue
回到未初始化状态,从而在下次使用时强制重新计算?
您 运行 遇到两个问题:
val
是不可变的,即初始化后不能更改
- 即使您改为使用
var
,它也没有在一段时间后过期的机制
我的建议是将 getDayOfWeek
变成一个在其他实例中跟踪当前值和状态的函数:
private var dayOfWeek: Option[Day] = None
private var lastEvaluated: Int = 0
def getDayOfWeek = dayOfWeek match {
case None => expensiveGetDayOfWeek
case Some(day) =>
if (DateTime.now.getDayOfYear > lastEvaluated) expensiveGetDayOfWeek
else day
}
private def expensiveGetDayOfWeek: Day = {
dayOfWeek = Some(someExpensiveOperation())
lastEvaluated = DateTime.now.getDayOfYear
dayOfWeek.get
}
我对何时重新计算的状态跟踪有点老套,因此您需要自己想出办法,但基本要点是按需计算。
Is there a simple way
由于 "laziness" 是用一个字段来实现的,以跟踪初始化,简单的解决方案是用可变引用包装惰性 val。当然,您必须处理该引用的可变性。
scala> class V { lazy val v = System.currentTimeMillis }
defined class V
scala> @volatile var x = new V
x: V = V@77468bd9
scala> x.v
res0: Long = 1431212391127
scala> x.v
res1: Long = 1431212391127
scala> x = new V
x: V = V@28f67ac7
scala> x.v
res2: Long = 1431212407970
然后是
scala> import concurrent._, duration._, ExecutionContext.Implicits.global
import concurrent._
import duration._
import ExecutionContext.Implicits.global
scala> implicit class ex(val d: Deadline) extends AnyVal { def expiring(f: => Unit) =
| Future(Await.ready(Promise().future, d.timeLeft)) onComplete (_ => f) }
defined class ex
scala> 10 seconds fromNow expiring { x = new V }
scala> x.v
res4: Long = 1431212407970
scala> x.v
res5: Long = 1431212407970
scala> x.v
res6: Long = 1431213010180
我可能想使用一种昂贵的方法,return结果取决于副作用。例如,取决于一天/一周的时间和 Monte Carlo 量子时间动力学模拟。因为它很贵而且我可能不需要它,所以我会使用 Scalas lazy val
lazy val maybeUnusedValue = getDayOfWeek
现在 12 个小时过去了,我的程序仍然 运行。我想重新计算,因为我的一天可能在此期间发生了变化。
是否有一种简单的方法可以强制 Scala return maybeUnusedValue
回到未初始化状态,从而在下次使用时强制重新计算?
您 运行 遇到两个问题:
val
是不可变的,即初始化后不能更改- 即使您改为使用
var
,它也没有在一段时间后过期的机制
我的建议是将 getDayOfWeek
变成一个在其他实例中跟踪当前值和状态的函数:
private var dayOfWeek: Option[Day] = None
private var lastEvaluated: Int = 0
def getDayOfWeek = dayOfWeek match {
case None => expensiveGetDayOfWeek
case Some(day) =>
if (DateTime.now.getDayOfYear > lastEvaluated) expensiveGetDayOfWeek
else day
}
private def expensiveGetDayOfWeek: Day = {
dayOfWeek = Some(someExpensiveOperation())
lastEvaluated = DateTime.now.getDayOfYear
dayOfWeek.get
}
我对何时重新计算的状态跟踪有点老套,因此您需要自己想出办法,但基本要点是按需计算。
Is there a simple way
由于 "laziness" 是用一个字段来实现的,以跟踪初始化,简单的解决方案是用可变引用包装惰性 val。当然,您必须处理该引用的可变性。
scala> class V { lazy val v = System.currentTimeMillis }
defined class V
scala> @volatile var x = new V
x: V = V@77468bd9
scala> x.v
res0: Long = 1431212391127
scala> x.v
res1: Long = 1431212391127
scala> x = new V
x: V = V@28f67ac7
scala> x.v
res2: Long = 1431212407970
然后是
scala> import concurrent._, duration._, ExecutionContext.Implicits.global
import concurrent._
import duration._
import ExecutionContext.Implicits.global
scala> implicit class ex(val d: Deadline) extends AnyVal { def expiring(f: => Unit) =
| Future(Await.ready(Promise().future, d.timeLeft)) onComplete (_ => f) }
defined class ex
scala> 10 seconds fromNow expiring { x = new V }
scala> x.v
res4: Long = 1431212407970
scala> x.v
res5: Long = 1431212407970
scala> x.v
res6: Long = 1431213010180