Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
您将如何在Scala中实现缓存方面_Scala_Caching_Aop_Python Decorators - Fatal编程技术网

您将如何在Scala中实现缓存方面

您将如何在Scala中实现缓存方面,scala,caching,aop,python-decorators,Scala,Caching,Aop,Python Decorators,头脑风暴:我正在从事一个Scala项目,在该项目中,我们进行服务调用,需要使用memcache缓存返回值。我当时正在从事一个Python项目,该项目旨在对返回值应该缓存的函数进行注释。我正在Scala中寻找一种类似的方法来为函数添加缓存特性 假设我有这个函数def callingService(arg1:String,arg2:Int):String我想要 基于函数名和参数计算缓存键 如果缓存不包含密钥,请执行服务调用 序列化返回值并将其存储在缓存中 否则,反序列化缓存值并返回它 调用cal

头脑风暴:我正在从事一个Scala项目,在该项目中,我们进行服务调用,需要使用memcache缓存返回值。我当时正在从事一个Python项目,该项目旨在对返回值应该缓存的函数进行注释。我正在Scala中寻找一种类似的方法来为函数添加缓存特性

假设我有这个函数
def callingService(arg1:String,arg2:Int):String
我想要

  • 基于函数名和参数计算缓存键
  • 如果缓存不包含密钥,请执行服务调用
  • 序列化返回值并将其存储在缓存中
  • 否则,反序列化缓存值并返回它

调用callingService的任何代码都不应该知道缓存。callingService的实现应该只调用服务X并返回一个字符串值,而不处理缓存内容。

我不知道在Scala中自动实现这一点的方法。我想你自己会做的

您希望任何调用代码都了解缓存。我认为实现这一点的唯一方法是在函数本身中使用缓存机制

为什么不使用闭包:

val cachedFunc = {
  val cache = mutable.Map[Int, Double]()

  def internalFunc(y: Int) : Double = Math.sqrt(y);

  (y: Int) => {
    if (cache.keySet.contains(y))
      cache(y)
    else
    {
      val result = internalFunc(y);
      cache += y -> result;
      result
    }
  }
}
现在您可以:

cachedFunc(200)

我更喜欢堆叠特征模式和蛋糕模式:

class Service {
  def callingService(arg1: String, arg2: Int): String = "ok"
}

trait Memo[K, V] {
  def cache(k: K)(v : => V): V
}

trait ServiceCache extends Service {
  self : Memo[(String, Int), String] =>

  abstract override def callingService(arg1: String, arg2: Int): String =
    cache((arg1, arg2)) { super.callingService(arg1, arg2) }
}

trait MapCache[K, V] extends Memo[K, V] {
  private val _cache = new collection.mutable.HashMap[K, V]
  def cache(k: K)(v : => V): V = _cache.getOrElseUpdate(k, v)
}
使用示例:

val service = new Service with ServiceCache with MapCache[(String, Int), String]

当然,您可以实现自己的缓存策略,并在创建服务时使用它。

scalaz提供了一个很好的缓存实现:

请注意,cake模式可能会引入太多的boilterplate,并可能最终成为难以维护的模式之一。我最近遇到了一个类似的情况,最终不得不放弃蛋糕图案。也许读卡器monad是一个更好的选择,或者是隐含的。奥德斯基在试验了其他替代方案后宣布,这是他的选择。选中此项: