I run lots of heavy computations in R, and I am trying to write a function that would help me cache my results and only compute them if necessary. I came up with this:
memoize <- function(filename, fun, ...){
if(file.exists(filename)){
message(paste("Reading", filename))
return(readRDS(filename))
} else {
message(paste(filename, "not found, running computations"))
result <- do.call(fun, list(...))
message(paste("Writing", filename))
saveRDS(result, filename)
return(result)
}
}
which allows me to do:
result <- memoize("test.rds", function(){ return(runif(100))} )
This works just fine, however, I want to be able to do without the "function()" part, i.e. pass an expression instead of a function. This can be done as follows:
memoize <- function(filename, expr){
if(file.exists(filename)){
message(paste("Reading", filename))
return(readRDS(filename))
} else {
message(paste(filename, "not found, running computations"))
f <- function(){}
body(f) <- expr
environment(f) <- parent.frame()
result <- do.call(f, list())
message(paste("Writing", filename))
saveRDS(result, filename)
return(result)
}
}
as per capturing an expression as a function body in R
This works fine when using
result <- memoize("test.rds", { runif(100)} )
However, I would like to keep the explicit return() statements in that expression. When I try
result <- memoize("test.rds", { return(runif(100))} )
I get
no function to return from, jumping to top level
I clearly misunderstand how this works: why does expr seem to be evaluated before being bound to f? And how could I achieve this?