在Kotlin中的记忆功能
我有一个实例方法buildHierarchyUncached的现有类,其签名可以在下面找到。
private fun buildHierarchyUncached(date: LocalDate): Node { ... }
我想提供一个公共函数 buildHiearchy,它是buildHierarchyUncached的memoized版本。 我可以接近我想要的东西:
val buildHiearchy = Memoize<LocalDate, Node>({buildHierarchy(it)})
这可以被称为像:
hierarchyService.buildHiearchy(businessDate)
使用:
class Memoize<I, O>(val func: (I) -> O): (I) -> O{ val cache = hashMapOf<I, O>(); override fun invoke(p1: I): O { return cache.getOrPut(p1, { func(p1) } ) } }
我希望能够将memoized函数声明为一个函数,而不是一个属性,虽然我认为它有助于可读性,但这不是一个大问题。 喜欢这个:
fun buildHierarchy(date: LocalDate): Node = Memoize<LocalDate, Node>({ buildHierarchyUncached(it)})
但是不能编译:“类型不匹配,必需节点,找到memoize”。
另外,为什么不编译?
val buildHiearchy = Memoize<LocalDate, Node>({(date) -> buildHierarchy(date)})
根据问题的性质,您需要一个类字段来存储您的缓存(缓存的值或缓存对象或委托)。 所以你必须在类中声明一个val
,因为函数不能这样做。
请注意,当您声明buildHiearchy
值时,您将得到两件事情:在类字段中存储Memoize<..>(..)
对象,并获取invoke()
函数(在其他位置声明,但仍然..) 。 我知道没有办法可以声明一个函数,并获得没有额外的语法的字段存储。
代码片段使用过时的语法。 像这样修正(无括号):
val buildHiearchy = Memoize<LocalDate, Node>({date -> buildHierarchy(date)})
以下解决方案适用于单参数函数。 如果你想创建一个缓存版本的功能bar
你只需要声明这样的:
val cachedBar = makeFunctionCache({ bar(it) })
这个实现将缓存存储在一个闭包中,这样就不需要把它放在一个专门的类中:
fun <X, R> makeFunctionCache(fn: (X) -> R): (X) -> R { val cache: MutableMap<X, R> = HashMap() return { cache.getOrPut(it, { fn(it) }) } }