记忆功能在Kotlin中

Bra*_*son 7 functional-programming kotlin

我有一个现有的类,其实例方法为buildHierarchyUncached,其签名可以在下面找到.

private fun buildHierarchyUncached(date: LocalDate): Node { ... }
Run Code Online (Sandbox Code Playgroud)

我想提供一个公共函数 buildHiearchy,它是buildHierarchyUncached的memoized版本.我可以接近我想要的东西:

val buildHiearchy = Memoize<LocalDate, Node>({buildHierarchy(it)})
Run Code Online (Sandbox Code Playgroud)

可以这样称为:

hierarchyService.buildHiearchy(businessDate)
Run Code Online (Sandbox Code Playgroud)

使用:

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) } )
  }
}
Run Code Online (Sandbox Code Playgroud)

我希望能够将memoized函数声明为函数而不是属性,这不是一个大问题,尽管我认为它有助于提高可读性.像这样:

fun buildHierarchy(date: LocalDate): Node = Memoize<LocalDate, Node>({ buildHierarchyUncached(it)})
Run Code Online (Sandbox Code Playgroud)

但是这不会编译:"类型不匹配.必需的节点.找到memoize."

另外,为什么不编译呢?

val buildHiearchy = Memoize<LocalDate, Node>({(date) -> buildHierarchy(date)})
Run Code Online (Sandbox Code Playgroud)

Eli*_*son 10

以下解决方案适用于单参数函数。如果您想创建该函数的缓存版本,bar您只需像这样声明它:

val cachedBar = makeFunctionCache({ bar(it) })
Run Code Online (Sandbox Code Playgroud)

该实现将缓存存储在闭包中,以便您无需将其放入专用类中:

fun <X, R> makeFunctionCache(fn: (X) -> R): (X) -> R {
    val cache: MutableMap<X, R> = HashMap()
    return {
        cache.getOrPut(it, { fn(it) })
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 您能否修改您的问题并更详细地解释您需要做什么?我不清楚为什么关闭解决方案不起作用。它看起来和工作起来都像任何其他函数。如果该函数实际上是接口的一部分,则存在差异,但更多信息会很有用。 (2认同)

Ily*_*man 7

使用Map.computeIfAbsent

val map = HashMap<LocalDate, Node>()
val key = LocalDate("Jun 14, 2022")

val value = map.computeIfAbsent(key) { 
    Node("My fancy node") 
}
Run Code Online (Sandbox Code Playgroud)

计算仅执行一次并存储在map


vod*_*dan 5

根据问题的性质,您需要一个类字段来存储缓存(缓存的值或缓存对象或委托)。因此,您必须val在类中的某个位置声明一个a ,因为函数无法做到这一点。

请注意,在声明buildHiearchy值时,一举两得:将Memoize<..>(..)对象存储在类字段中,然后得到invoke()函数(在其他地方声明,但仍然声明..)。我不知道您可以声明一个函数并以其他语法获取字段存储。

该代码段使用了过时的语法。像这样解决(无括号):

val buildHiearchy = Memoize<LocalDate, Node>({date -> buildHierarchy(date)})
Run Code Online (Sandbox Code Playgroud)

  • 好吧,这就是我的观点 - 如果某个地方没有字段,你就不可能拥有这样的函数 (2认同)