How to memoize a method?


#1

Hello !

I would like to memoize a method of a class and be able to access this class properties. Example:

class A( val m: ConcurrentHashMap<Int,Int> ) {
  val f = { y: Int -> y * 2 ).memoize()
}

where memoize:

fun (A.(Int) -> Int).memoize(): (Int) -> Int {
    return object: (Int) -> Int {
        override fun invoke(p1: Int): Int {
            val r = p1 * 10
            A.m.putIfAbsent(p1, r)
            return r
        }
    }
}

However I get error:
Error:(6, 7) Kotlin: Unresolved reference. None of the following candidates is applicable because of receiver type mismatch: public fun (A.(Int) -> Int).memoize(): (Int) -> Int defined in test.kmem in file main.kt

Is there a way to to do above?

Best Regards,
marcino239


#2

That particular compiler error can be resolved by adjusting class A as follows:

class A( val m: Map<Int,Int> ) {
  val f = run {
    val g: A.(Int)-> Int = { y: Int -> y * 2 }
      
    g.memoize()
  }
}

The memoize function itself does not compile though. I cannot help here, as I am not sure about what you want to achieve.


#3

Is this what you want to achieve?

class A {
  val f = { y: Int -> y * 2 }.memoize()
}

fun ((Int) -> Int).memoize(): (Int) -> Int {
  val mem = ConcurrentHashMap<Int, Int>()
  
  return { p1 ->
    val r = this(p1)
    mem.putIfAbsent(p1, r)
    r
  }
}

#4

Thanks! The trick with run solves the compiler error, but is it possible to access A.m from memoize? The idea is to be able to inspect all cached calls. Full code is below, but then I get error: Error:(16, 17) Kotlin: Unresolved reference: @A

import java.util.concurrent.ConcurrentHashMap

class A( val m: ConcurrentHashMap<Int,Int> ) {
    val f = run {
        val g: A.(Int)-> Int = { y: Int -> y * 2 }
        g.memoize()
    }
}

fun (A.(Int) -> Int).memoize(): (Int) -> Int {
    return object: (Int) -> Int {
        override fun invoke(p1: Int): Int {
            val r = this@memoize(this@A, p1)
            this@A.m.putifAbsent(p1,r)
            return r
        }
    }
}

fun main( args: Array<String> ) {
    val m = ConcurrentHashMap<Int,Int>()
    val a = A(m)
    println( a.f(2) )
    println( m )  // expecting {2=4}
}