Caching is based on the assumption that if the input does not change, the output will not change. After an expression is executed for the first time, its result will be saved (either in memory or on disk). The next run will be skipped and the previously saved result will be loaded directly if all external inputs of the expression remain the same, otherwise the cache will be invalidated and the expression will be re-executed.
Arguments
- expr
An R expression to be cached.
- path
The path to save the cache. The special value
":memory:"means in-memory caching. If it is intended to be a directory path, please make sure to add a trailing slash.- id
A stable and unique string identifier for the expression to be used to identify a unique copy of cache for the current expression from all cache files (or in-memory elements). If not provided, an MD5 digest of the deparsed expression will be used, which means if the expression does not change (changes in comments or white spaces do not matter), the
idwill remain the same. This may not be a good default is two identical expressions are cached under the samepath, because they could overwrite each other's cache when one expression's cache is invalidated, which may or may not be what you want. If you do not want that to happen, you need to manually provide anid.- ...
More arguments to control the behavior of caching (see ‘Details’).
Value
If the cache is found, the cached value of the expression will be loaded and returned (other local variables will also be lazy-loaded into the current environment as a side-effect). If cache does not exist, the expression is executed and its value is returned.
Details
Arguments supported in ... include:
vars: Names of local variables (which are created inside the expression). By default, local variables are automatically detected from the expression viafind_locals(). Locally created variables are cached along with the value of the expression.hashandextra: R objects to be used to determine if cache should be loaded or invalidated. If (the MD5 hash of) the objects is not changed, the cache is loaded, otherwise the cache is invalidated and rebuilt. By default,hashis a list of values of global variables in the expression (i.e., variables created outside the expression). Global variables are automatically detected byfind_globals(). You can provide a vector of names to override the automatic detection if you want some specific global variables to affect caching, or the automatic detection is not reliable. You can also provide additional information via theextraargument. For example, if the expression reads an external filefoo.csv, and you want the cache to be invalidated after the file is modified, you may useextra = file.mtime("foo.csv").keep: By default, only one copy of the cache corresponding to anidunderpathis kept, and all other copies for thisidis automatically purged. IfTRUE, all copies of the cache are kept. IfFALSE, all copies are removed, which means the cache is always invalidated, and can be useful to force re-executing the expression.rw: A list of functions to read/write the cache files. The list is of the formlist(name = 'xxx', load = function(file) {}, save = function(x, file) {}). By default,readRDS()andsaveRDS()are used. This argument can also take a character string to use some built-in read/write methods. Currently available methods includerds(the default),raw(usingserialize()andunserialize()),qs2(usingqs2::qs_read()andqs2::qs_save()), andqdata(usingqs2::qd_read()andqs2::qd_save()). Therdsandrawmethods only use base R functions (therdsmethod generates smaller files because it uses compression, but is often slower than therawmethod, which does not use compression). Theqs2andqdatamethods require the qs2 package, which can be much faster than base R methods and also supports compression.
References
See https://pkg.yihui.org/litedown/book/#sec:option-cache for how it works and an application in litedown.
Examples
# the first run takes about 1 second
y1 = xfun::cache_exec({
x = rnorm(1e+05)
Sys.sleep(1)
x
}, path = ":memory:", id = "sim-norm")
# the second run takes almost no time
y2 = xfun::cache_exec({
# comments won't affect caching
x = rnorm(1e+05)
Sys.sleep(1)
x
}, path = ":memory:", id = "sim-norm")
# y1, y2, and x should be identical
stopifnot(identical(y1, y2), identical(y1, x))