如何在scala中缓存函数结果

时间:2018-04-21 01:56:26

标签: scala

假设我实现了一个案例类来计算confusion matrix

的一些度量
case class Measure(tp: Int, fp: Int, fn: Int){
  require(tp < 0); require(fp < 0); require(fn < 0)

  def precision: Double = tp / (tp + fp)
  def recall: Double = tp / (tp + fn)
  def fMeasure: Double = 2 * (precision * recall) / (precision + recall)
}

关于Scala如何处理这些功能,我有一些问题:

  1. 如果有人拨打fMeasureprecisionrecall都会被叫两次?或者Scala编译器会发现我们使用相同的值并缓存第一次调用的结果并重新使用记忆值进行第二次调用

  2. 如果有人在之前调用了precisionrecall,那么这些结果会在某处缓存,以便fMeasure不必重新计算precision和{{ 1}}

  3. 如果两者都没有以任何类型的计算优化结束,那么是否有特定的&#34; scala&#34;缓存结果的方法?来自Java背景,我会创建一个名为recallprecision的字段,并检查recall以缓存结果。

1 个答案:

答案 0 :(得分:2)

首先,代码中存在错误。

将函数精度重写为

def precision: Double = tp.toDouble / (tp.toDouble + fp.toDouble)

同样你必须修复召回功能。

Q值。如果有人打电话给fMeasure,精确度和召回都会被调用两次吗?

答。是。他们会被叫两次。

解释第二个问题。

Q值。有没有办法阻止它被调用两次。

答。是。使用懒惰的val。

所以代码可以是这样的。我已经取消了defs并使用了lazy vals,因为它不明显为什么你需要defs在这里。

case class Measure(tp: Int, fp: Int, fn: Int){
  require(tp < 0); require(fp < 0); require(fn < 0)

  lazy val precision = tp.toDouble / (tp.toDouble + fp.toDouble)
  lazy val recall = tp.toDouble / (tp.toDouble + fn.toDouble)
  lazy val fMeasure = 2 * (precisionVal * recallVal) / (precisionVal + recallVal)

}

与懒惰相关的成本。见这 - https://dzone.com/articles/cost-laziness

希望这有帮助。