Last active
September 25, 2020 14:33
-
-
Save jeroenjanssens/3e27381a799e4449c9bd to your computer and use it in GitHub Desktop.
Cache the result of an expression in R
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#' Cache the result of an expression. | |
#' | |
#' Use \code{options(cache.path = "...")} to change the cache directory (which | |
#' is the current working directory by default). | |
#' | |
#' @param expr expression to evaluate | |
#' @param key basename for cache file | |
#' @param ignore_cache evalute expression regardless of cache file? | |
#' @return result of expression or read from cache file | |
#' | |
#' @example | |
#' answer <- cache({ | |
#' \dontrun{ | |
#' Sys.sleep(7500000 * 365 * 86400) | |
#' } | |
#' 42 | |
#' }, "life_universe_everything") | |
#' | |
#' @seealso \code{\link[R.cache]} | |
cache <- function(expr, key, ignore_cache = FALSE) { | |
filename <- file.path(getOption("cache.path", "."), paste0(key, ".rds")) | |
if (!ignore_cache && file.exists(filename)) { | |
message(sprintf("Loading result from %s", filename)) | |
result <- readRDS(filename) | |
} else { | |
result <- expr | |
message(sprintf("Saving result to %s", filename)) | |
saveRDS(result, filename) | |
} | |
result | |
} |
You could even invalidate the cache automatically when the parse tree of the cached expression changes.
`%<cache-%` <- function(key, value) {
key <- substitute(key)
stopifnot(is.name(key))
previoushash = "none"
hash <- digest::digest(substitute(value))
filename <- file.path(getOption("cache.path", "."), paste0(deparse(key), ".rds"))
hashfilename <- file.path(getOption("cache.path", "."), paste0(deparse(key), ".hash"))
if (file.exists(hashfilename)) {
previoushash <- readRDS(hashfilename)
}
if (file.exists(filename) & (hash == previoushash) & !getOption("refresh.cache", F)) {
message(sprintf("Loading result from %s", filename))
value <- readRDS(filename)
} else {
message(sprintf("Saving result to %s", filename))
saveRDS(value, filename)
saveRDS(hash, hashfilename)
}
assign(as.character(key), value, env = parent.frame())
invisible(key)
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks @jamesonquinn, that makes sense. This allows you to refresh the cache in an interactive way, rather than changing the code.