2

如何使用函数式编程实现缓存

几天前,我遇到了使用 scala 的回调和代理模式实现。如果值不在地图中,则此代码应仅应用内部函数。但是每次重新初始化地图并且值都消失了(这似乎很明显。

如何在不同的函数调用之间一次又一次地使用相同的缓存

class Aggregator{
  def memoize(function: Function[Int, Int] ):Function[Int,Int] = {
    val cache = HashMap[Int, Int]()
     (t:Int) => {
      if (!cache.contains(t)) {
        println("Evaluating..."+t)
        val r = function.apply(t);
        cache.put(t,r)
        r
      }
       else
      {
        cache.get(t).get;
      }
    }
  }

  def memoizedDoubler = memoize( (key:Int) => {
    println("Evaluating...")
    key*2
    })
  }

object Aggregator {

  def main( args: Array[String] ) {
    val agg = new Aggregator()
    agg.memoizedDoubler(2)
    agg.memoizedDoubler(2)// It should not evaluate again but does
    agg.memoizedDoubler(3)
    agg.memoizedDoubler(3)// It should not evaluate again but does

 }
4

3 回答 3

1

我知道您在这里尝试做什么,它不起作用的原因是每次您调用memoizedDoubler它都是第一次调用memorize。如果您希望它只调用一次,则需要声明memoizedDoubler为 aval而不是。defmemoize

  val memoizedDoubler = memoize( (key:Int) => {
    println("Evaluating...")
    key*2
  })

def这个答案对和之间的区别有很好的解释valhttps://stackoverflow.com/a/12856386/37309

于 2016-04-20T21:52:11.393 回答
1

你不是在Map每次调用中声明一个新的吗?

def memoize(function: Function[Int, Int] ):Function[Int,Int] = {
    val cache = HashMap[Int, Int]()

而不是为每个实例指定一个Aggregator

例如

class Aggregator{
  private val cache = HashMap[Int, Int]()
  def memoize(function: Function[Int, Int] ):Function[Int,Int] = {
于 2016-04-12T10:13:09.620 回答
0

要回答您的问题:

如何使用函数式编程实现缓存

在函数式编程中没有可变状态的概念。如果要更改某些内容(例如缓存),则需要返回更新的缓存实例以及结果并将其用于下一次调用。

这是遵循该方法的代码修改。function计算值并cache纳入Aggregator. 当memoize被调用时,它返回元组,其中包含计算结果(可能从缓存中获取)和Aggregator应该用于下一次调用的新的。

class Aggregator(function: Function[Int, Int], cache:Map[Int, Int] = Map.empty) {

  def memoize:Int => (Int, Aggregator) = {
    t:Int =>
      cache.get(t).map {
        res =>
          (res, Aggregator.this)
      }.getOrElse {
        val res = function(t)
        (res, new Aggregator(function, cache + (t -> res)))
      }
  }
}

object Aggregator {

  def memoizedDoubler = new Aggregator((key:Int) => {
    println("Evaluating..." + key)
    key*2
  })


  def main(args: Array[String]) {
    val (res, doubler1)  = memoizedDoubler.memoize(2)
    val (res1, doubler2)  = doubler1.memoize(2)
    val (res2, doubler3)  = doubler2.memoize(3)
    val (res3, doubler4)  = doubler3.memoize(3)
  }
}

这打印:

Evaluating...2
Evaluating...3
于 2016-04-21T01:24:21.340 回答