functional-programmingkotlin

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

Solution

  • By the nature of the problem, you need a class field to store your cache (the cached value or a caching object or a delegate). So you have to declare a val in the class somewhere, since functions can't do that.

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

    The code snippet uses outdated syntax. Fix like this (no parentheses):

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