Search code examples
rmemoizationmemoise

Memoise a function taking a function as argument


I want to do some memoization using the R package memoise on the following function taking as argument a function:

library(memoise)

func      = function(x) x
slowFunc  = function(a,f,b=2) {Sys.sleep(1); a+b}
quickFunc = memoise(slowFunc)

> system.time(slowFunc(2, func, 3))
   user  system elapsed 
      0       0       1 
> system.time(slowFunc(2, func, 3))
   user  system elapsed 
   0.00    0.00    0.99 

There are two successive calls and the second returns 1 sec on the timing whereas I could have expected something instantaneous.

It is weird but it seems memoise do not apply when arguments are functions ... how the function is represented in the memory to have this working?


Solution

  • Your code doesn't use the memoized function. It calls the original function which results in a 1 second sleep.

    If you try with system.time(quickFunc(2, func, 3)) you'll see that there is no delay the second time.

    memoise works only with function arguments, and returns a function that either returns the cached value, or calls the input function to create it. While

    m<-memoise(5)
    

    won't raise an error, trying to call it (eg with m(5)) will return an the following error

    Error in mm() : could not find function "f"
    

    You can check the function's code by simply typing memoise. The result

    function (f) 
    {
        cache <- new_cache()
        memo_f <- function(...) {
            hash <- digest(list(...))
            if (cache$has_key(hash)) {
                cache$get(hash)
            }
            else {
                res <- f(...)
                cache$set(hash, res)
                res
            }
        }
        attr(memo_f, "memoised") <- TRUE
        return(memo_f)
    }
    

    shows that memoise creates a hash of all the arguments and uses it as the key to an in-memory cache, even if these are functions.