我在Scala中有一个Option[…]类型的变量。
我需要:
即它应该像一些长期计算的供应商方法的缓存一样。
我当然可以用愚蠢的方式做到这一点:
var cache: Option[X]
…
{
if (cache.isEmpty) cache = Some(supplier())
cache.get
}
但是我相信应该有一种Java Map#computeIfAbsent风格的简单代码。
在吗?
答案 0 :(得分:2)
您不能在一行中完成此操作,因为您必须先进行赋值以更新cache
,然后进行提取以获取值:
cache = cache orElse Some(supplier())
cache.get
赋值返回Unit
,因此您不能使用赋值的结果来读取值。
这种代码模式有时称为“记忆”,并且在stackoverflow和其他地方有很多通用代码示例。
答案 1 :(得分:-1)
经过一番思考,我意识到甚至在理论上Option
的Scala中都不存在这样的事情。因为Option
被设计为不可变的(与Java Map
不同),所以它没有更新其值的更新方法(甚至更多— None
和Some
不同Option
的子类)。我们都无法编写诸如def getOrFill[T](ref cache: Optional[T])(supplier: => T): T
之类的外部辅助方法,因为Scala不支持ref
(输入-输出)参数。
我们可能最好的办法是创建一个单独的用于缓存的类(用Option
包装):
变种1:
class Cache[T] {
def getOrFill(supplier: => T): T = {
if (value.isEmpty) value = Some(supplier)
value.get
}
private var value: Option[T] = None
}
然后
var cache = new Cache[X]
…
cache.getOrFill(supplier())
变体2-如果在缓存的整个生命周期中都使用了相同的供应商(最可能的情况):
class Cache[T](supplier: => T) {
def getOrFill: T = {
if (value.isEmpty) value = Some(supplier)
value.get
}
private var value: Option[T] = None
}
然后
var cache = new Cache[X](supplier())
…
cache.getOrFill
注意:我没有考虑以上代码的差异(也许应该更改差异)。