缓存使用功能回调/代理模式实现scala

时间:2016-04-12 10:09:27

标签: scala caching functional-programming proxy-pattern

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

几天前,我遇到了使用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

 }

3 个答案:

答案 0 :(得分:1)

您是不是每次调用都声明一个新的Map

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

而不是指定{em>每个实例一个 Aggregator

e.g。

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

答案 1 :(得分:1)

我看到你在这里尝试做什么,它不起作用的原因是每次你打电话memoizedDoubler它首先打电话memorize。如果您希望memoizedDoubler只调用val一次,则需要将def声明为memoize而不是 val memoizedDoubler = memoize( (key:Int) => { println("Evaluating...") key*2 })

def

这个答案很好地解释了valID 2之间的区别。 https://stackoverflow.com/a/12856386/37309

答案 2 :(得分: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