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

cache using functional callbacks/ proxy pattern implementation scala

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

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

 }

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

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

而不是指定 每个实例一个 of Aggregator ?

例如

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

我明白你在这里想做什么,它不起作用的原因是每次你调用 memoizedDoubler 它首先调用 memorize。如果您希望它只调用一次 memoize,则需要将 memoizedDoubler 声明为 val 而不是 def

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

这个回答很好的解释了defval的区别。

回答你的问题:

How to implement cache using functional programming

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

这里是按照该方法对您的代码进行的修改。 function 计算值,cache 合并到 Aggregator。当调用 memoize 时,它是 returns 元组,其中包含计算结果(可能从缓存中获取)和应该用于下一次调用的新 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