Is there a way to copy a closure to a new object that contains the current status of the original closure while also being separated for all upcoming changes in the environment?
I have tried to come up with a solution, but it fails with an error when I try using the contained function: Error in { : could not find function "{"
Here's a code example:
# basic incrementation closure
inc <- function() {
i <- 0
function(x = 1) {
i <<- i + x
i
}
}
copyClosure <- function(x) {
oldEnv <- environment(x)
# set up copy of x in new env
ret <- x
newEnv <- new.env(parent = emptyenv())
environment(ret) <- newEnv
# copy objects from old to new env
objs <- ls(envir = oldEnv, all.names = TRUE, sorted = FALSE)
for (ii in objs) assign(x = ii, envir = newEnv, value = get(x = ii, envir = oldEnv))
return(ret)
}
# original closure object
foo <- inc()
foo(5)
bar <- copyClosure(foo)
# check if objects i are identical
identical(x = get(x = "i", envir = environment(foo)),
y = get(x = "i", envir = environment(bar)))
# check if objects i are separated
foo(5)
identical(x = get(x = "i", envir = environment(foo)),
y = get(x = "i", envir = environment(bar)))
# try using copied closure
bar(5)
Change the parent of the new environment to match the old environment
newEnv <- new.env(parent = parent.env(oldEnv))
Then it seems to work as intended.
foo <- inc()
foo(5)
# [1] 5
bar <- copyClosure(foo)
identical(x = get(x = "i", envir = environment(foo)),
y = get(x = "i", envir = environment(bar)))
# [1] TRUE
foo(5)
# [1] 10
identical(x = get(x = "i", envir = environment(foo)),
y = get(x = "i", envir = environment(bar)))
# [1] FALSE
bar(5)
# [1] 10