How to memoise a function at package startup in R

441 Views Asked by At

I work on an R package which wraps API calls. In order to reduce the number of actual calls and to speed things up, I memoise the function making the API call. To do so, I created the following function, which allows to set the cache directory:

memoise_fromJSON <- function(cache_dir = tempdir()) {
  memoise::memoise(jsonlite::fromJSON,
                   cache = memoise::cache_filesystem(cache_dir))
}

To create the memoised function I use

memoised_fromJSON <- memoise_fromJSON()

Now, since I need the memoised function many times within my package, I would like to memoise the function at package startup. I tried

.onLoad <- function(libname, pkgname) {
  memoised_fromJSON <- my_package:::memoise_fromJSON()
}

but I still need to run memoised_fromJSON <- memoise_fromJSON() to get it to work.

So my questions are:

  1. Is there a possibility to memoise a function at package startup?
  2. If so, how can I memoise the function in a way that it is not visible in the global environment?

I guess, the questions are somehow related. Is my understanding correct that my attempt with .onLoad() does not work because it creates the memoised function within the environment of .onLoad()?


PS: I am aware, that I cannot change the cache_dir at package loading, but I want to set a reasonable default which makes it possible to start without further ado. However, this keeps the possibility to change the cache directory if needed.

2

There are 2 best solutions below

0
On

You are performing a local assignment inside the onLoad function.

And you cannot simply perform a (package-) global assignment, since the package namespace is locked. What you can do is

  1. Create a new environment via new.env(parent = parent.env(environment()) (the parameter ensures that this environment finds objects defined inside your package namespace).
  2. Assign the memoised functions inside that environment.
  3. attach the environment. Now, this is generally frowned upon and will in fact earn you a red card from CRAN if you attempt to submit it. In fact, your .onLoad function mustn’t call attach since a user might want to use your package without attaching it. But I think it’s legitimate if you do this in .onAttach rather than .onLoad. The CRAN maintainers might not agree though, I’m afraid; then again, there’s precedence for CRAN packages that call attach under specific circumstances, e.g. {devtools}.
0
On

And why not directly declare the memoised function in your R sources ?

#' Memoised version of [jsonlite::fromJSON]
#' @inherit jsonlite::fromJSON
#' 
#' @export
memoised_fromJSON <- memoise::memoise(jsonlite::fromJSON,
                                      cache = memoise::cache_filesystem(tempdir()))

That should do the job without any notes or warnings in R CMD check.