Memoization function in Kotlin

I have an existing class with an instance method buildHierarchyUncached whose signature can be found below.

private fun buildHierarchyUncached(date: LocalDate): Node { ... } 

I would like to provide a public function buildHiearchy, which is a memoized version of buildHierarchyUncached. I can get closer to what I want:

 val buildHiearchy = Memoize<LocalDate, Node>({buildHierarchy(it)}) 

Which can be called as:

 hierarchyService.buildHiearchy(businessDate) 

Using:

 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) } ) } } 

I would like to be able to declare a memoized function as a function instead of a property that is not a huge deal, although I believe that it helps readability. Like this:

 fun buildHierarchy(date: LocalDate): Node = Memoize<LocalDate, Node>({ buildHierarchyUncached(it)}) 

but this does not compile: "Type mismatch. Required Node. Memoize found."

Also, why is this not compiling?

 val buildHiearchy = Memoize<LocalDate, Node>({(date) -> buildHierarchy(date)}) 
+5
source share
2 answers

By the nature of the problem, you need a class field for storing the cache (cached value or cached object or delegate). Thus, you should declare val in the class somewhere, since functions cannot do this.

Note that when you declare your buildHiearchy value, you get two things in one: you store the Memoize<..>(..) object in the class field and get the invoke() function (declared somewhere else, but still. ..). I do not know how you can declare a function and get field storage without additional syntax.

The code snippet uses outdated syntax. Correct this (without parentheses):

 val buildHiearchy = Memoize<LocalDate, Node>({date -> buildHierarchy(date)}) 
+4
source

The following solution works for functions with one argument. If you want to create a cached version of the bar function, you simply declare it as follows:

 val cachedBar = makeFunctionCache({ bar(it) }) 

The implementation stores the cache in closure, so you do not need to put it in a dedicated class:

 fun <X, R> makeFunctionCache(fn: (X) -> R): (X) -> R { val cache: MutableMap<X, R> = HashMap() return { cache.getOrPut(it, { fn(it) }) } } 
+1
source

Source: https://habr.com/ru/post/1242671/


All Articles