TL;DR: How can I make a subclass of the base R environment type so that I can make a record of anytime R asks if a value exists in this environment?
I'm working on a slightly smarter caching process to help me with a project I'm working on. My initial approach was to digest the function or function body when the function is run. However, this seems to be too fragile: a new cache entry needs to be added any time there is a new entry in the file with the function's source. I could do a character representation of the function body, but the problem is that this wouldn't update if the definition changes because of an update of a function called within the body.
My envisioned solution is to execute the function body within an environment that keeps track of which entries (most importantly, which other R functions I've written) are accessed, and when checking whether a cache result is valid, including a digest of those functions too. I've tried this with different functions ($
, [[
, names
) but none seem to be called in the evalq
expression at the end.
If it is the case that this is internal and can't be modified with R subclassing, then that is good to know too.
I'm trying to merely print out the name of the variable being looked for in this reprex:
cachingEnv <- setClass("cachingEnv", contains = "environment", slots = c(bodies = "list"))
setMethod("$", c("cachingEnv"),
function(x, name) {
cat(paste0("name is", name, "\n"))
ev <- as(x, "environment")
print(rlang::env_print(ev))
ev[[name]]
})
ce <- cachingEnv()
ce$x <- 3
ce$x
#> name isx
#> <environment: 0x5583674819f8>
#> parent: <environment: 0x55836747e338>
#> bindings:
#> * x: <dbl>
#> <environment: 0x5583674819f8>
#> [1] 3
evalq({x}, envir = ce)
#> [1] 3 <- This is where I'm wishing for results like with ce$x
Created on 2021-11-22 by the reprex package (v1.0.0)