0

All,

I am new to R6. I am trying to create a private object which is cached via the memoise function. The background idea is that this object will be defined by a computationally intensive calculation, which I would like to avoid rerunning after the first time.

I am trying to duplicate the following behaviour:

library(R6)
library(memoise)
library(digest)

Test <- memoise(function(x){
    rnorm(1e8)
})


Test(1)
Test(1)

You should observe that the first Test(1) takes a second or two to run, whereas the second Test(1) is instant.

My MWE in R6 world is:

factory <- R6Class("Test",
                private = list(
                               ..Z = memoise(
                                             function(x){
                                                         rnorm(1e8)
                                                         }
                                             )
                                         ),
                                         active = list(
                                                Z = function(value){
                                                       private$..Z(x=1)
                                                }
                                         )
                                     )

object <- factory$new()

object$Z

This should show me rnorm(1e8), but instead I get the error:

Error in private$..Z() : object 'cache' not found

A quick edit of my object lets me know that under the hood, ..Z looks like:

function (...) 
{
    hash <- digest(list(...))
    if (cache$has_key(hash)) {
        cache$get(hash)
    }
    else {
        res <- f(...)
        cache$set(hash, res)
        res
    }
}

So it looks like I've been unsuccessful in setting up my memoise. Looking at the above, I'm not 100% clear on how memoise works - how does the cache exist if I can't see it? Usually not found errors are due to scoping, which gets complicated with private and R6.

www
  • 38,575
  • 12
  • 48
  • 84
T.Holme
  • 473
  • 4
  • 17

1 Answers1

0

The following works well for me. You will just have to implement the caching yourself

library(R6)
library(digest)

factory <- R6Class(
  "Test",
  private = list(
    cache = list(),
    ..Z = function(x){
      hash <- digest(x)
      if (hash %in% names(private$cache)) {
        private$cache[[hash]]
      }
      else {
        res <- rnorm(1e7, x)
        private$cache[[hash]] <- res
        res
      }
    }
  ),
  active = list(
    Z = function(value){
      private$..Z(x=1)
    }
  )
)

object <- factory$new()

## takes a while    
object$Z

## returns "instantly"
object$Z
Gregor de Cillia
  • 7,397
  • 1
  • 26
  • 43