为了完整起见,我还提出了一个可行的解决方案,但不太健壮。
超出范围的对象会在 R 中自动删除。但是,实际删除发生在 R 的垃圾回收 gc() 期间,无法直接控制。因此,要在 knit() 完成时移除对象,需要在 knit() 的环境中创建该对象,这比引擎调用高一些级别。
原则上,可以通过knit() 的on.exit() 注册一个进行实际清理的函数,parent.frame(n=...) 可以检索谁的环境。请注意,当注册到 on.exit() 的表达式被调用时,该范围内的所有对象仍然存在。
maxima.engine <- function(options) {
e <- parent.frame(n = sys.parent() - 2)
if(!exists("mx", envir = e)) {
message("starting maxima on first chunk")
assign(x = "mx", value = new(rmaxima:::RMaxima), envir = e)
assign(x = "execute", value = get("mx", envir = e)$execute, envir = e)
assign(x = "stopMaxima", value = get("mx", envir = e)$stopMaxima, envir = e)
# quit maxima "on.exit"ing of knit()
# eval() doesn't work on "special primitive functions
# do.call() does ... this may break in the future
# see https://stat.ethz.ch/pipermail/r-devel/2013-November/067874.html
do.call("on.exit", list(quote(stopMaxima()),
add = TRUE), envir = e)
}
code <- options$code
out <- character(0);
for(i in 1:length(code))
out <- c(out, eval(call("execute", code[i]), envir = e))
engine_output(options, code, out)
}