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 that is a memoized version of buildHierarchyUncached. I can get close to what I want:
val buildHiearchy = Memoize<LocalDate, Node>({buildHierarchy(it)})
Which can be called like:
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 the memoized function as a function instead of a property, which is not a huge deal, though I think it helps readability. Like this:
fun buildHierarchy(date: LocalDate): Node = Memoize<LocalDate, Node>({ buildHierarchyUncached(it)})
but that doesn't compile: "Type mismatch. Required Node. Found memoize."
Also, why doesn't this compile?
val buildHiearchy = Memoize<LocalDate, Node>({(date) -> buildHierarchy(date)})
You can achieve your goal with a Map.computeIfAbsent
, it will look something like that:
val map = HashMap<String, Any>()
fun doSomething():Any{
return map.computeIfAbsent("functionKey") {
// do your calculation here
}
}
This way, the calculation will be executed only once and stored in the map
The following solution works for single-argument functions. If you want to created a cached version of the function bar
you simply declare it like this:
val cachedBar = makeFunctionCache({ bar(it) })
The implementation stores the cache in a closure so that you don't 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) })
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With