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

I see what you're trying to do here, the reason it's not working is that every time you call memoizedDoubler it's first calling memorize. You need to declare memoizedDoubler as a val instead of def if you want it to only call memoize once.

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

This answer has a good explanation on the difference between def and val. https://stackoverflow.com/a/12856386/37309

于 2016-04-20T21:52:11.393 に答える
0

あなたの質問に答えるには:

関数型プログラミングを使用してキャッシュを実装する方法

関数型プログラミングには、可変状態の概念はありません。何か (キャッシュなど) を変更したい場合は、結果と共に更新されたキャッシュ インスタンスを返し、次の呼び出しに使用する必要があります。

これは、そのアプローチに従ったコードの変更です。function値を計算し、cacheに組み込まれてAggregatorいます。がmemoize呼び出されると、計算結果 (キャッシュから取得される可能性があります) とAggregator、次の呼び出しで使用される new を含むタプルを返します。

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 に答える