我不确定这个模式是什么被调用,但是这可以用scala编写,如果是这样的话我怎么去做呢?
val userId = 1
def getUser(userId: Int): User = {
CacheLookup.getOrElse(userId) {
userDao.get(userId)
}
}
我想这会是一个匿名函数作为参数吗?
答案 0 :(得分:2)
有类似于地图上的内容 - 查看可变地图&{39} withDefault
。不同之处在于它没有更新地图,这似乎是你想要的(事实上,很多人使用withDefault
想要的,我们得到的问题这里)。
另一种选择是 memoization 。您必须在标准库之外找到它,但它的工作方式有点类似,除非您没有明确地执行缓存操作。基本上,你编写一个函数userId => userDao.get(userId)
,然后你得到一个memoized版本。当您调用memoized版本时,它将检查是否有参数的缓存版本,如果是的话,请提供该版本。
请注意,缓存存在重要问题。你想要/可以让它无限增加,还是应该限制?密钥会在一段时间后过期吗?这种控制很重要,无论你选择哪种解决方案都必须支持它。
至于如何实现它,它可以是这样的:
def memoize[A, B](f: A => B): A => B = {
var map = Map.empty[A, B]
(key: A) => {
if (!map.contains(key)) map += key -> f(key)
map(key)
}
}
val getUser = memoize((userId: Int) => userDao.get(userId))
这个memoization函数接受一个Function1
(即一个带有一个参数的函数)并取一个Function1
进行缓存(在非常基本的意义上,没有我提到的任何控件)。对于获取更多参数的函数,您必须创建不同版本的函数,或者使它们 tupled 。
然后我们开始使用,我传递了一个userId
(一个Int
)的函数并返回一个User
,然后我们得到了相同的函数,但是现在做缓存。
以上是好奇心的一个例子:
scala> val mult = memoize(((x: Int, y: Int) => x * y).tupled)
mult: ((Int, Int)) => Int = <function1>
scala> mult(2, 3)
res18: Int = 6
scala> mult(2 -> 3)
res19: Int = 6
第一个电话mult(2, 3)
实际上是Scala的怪异。当调用带元组的函数时,如果传递多个参数,则Scala将自动进行元组编码。
答案 1 :(得分:1)
你所要求的并不完全清楚。如果您想知道如何实现getOrElse
方法以便只对数据库调用进行有条件的评估,那么答案就是使用普通的高阶函数:
def getOrElse(userId: Int)(getter: Int => User) =
if (cache contains userId)
cache get userId
else
getter(userId)