你会如何编写一个带有可选内部函数的方法

时间:2014-04-01 03:53:22

标签: scala

我不确定这个模式是什么被调用,但是这可以用scala编写,如果是这样的话我怎么去做呢?

val userId = 1

def getUser(userId: Int): User = {
 CacheLookup.getOrElse(userId) {
   userDao.get(userId)
 }
}

我想这会是一个匿名函数作为参数吗?

2 个答案:

答案 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)