【发布时间】:2021-06-10 15:19:01
【问题描述】:
给定一个在其临时环境中创建多个对象的函数:
myFun <- function(arg1 = "hey", arg2 = "bye") {
x <- paste(arg1, arg2)
y <- paste(x, "hey")
z <- paste(y, "again!")
return(z)
}
有没有可以提取另一个函数的临时环境的函数? 例如
myFun_env <- capture_env(myFun())
这将作为输出返回:
myFun_env <- rlang::env(
arg1 = "hey",
arg2 = "bye",
x = paste(arg1, arg2),
y = paste(x, "hey"),
z = paste(y, "again!")
)
> rlang::env_print(myFun_env)
<environment: 0x556959d73708>
parent: <environment: global>
bindings:
* x: <chr>
* y: <chr>
* z: <chr>
* arg1: <chr>
* arg2: <chr>
更新 1: 来自用户 G. Grothendieck https://stackoverflow.com/users/516548/g-grothendieck的解决方案
> trace(myFun, quote(assign(".Env", environment(), .GlobalEnv)), print = FALSE)
> myFun()
> rlang::env_print(.Env)
<environment: 0x556bf1a8ec08>
parent: <environment: global>
bindings:
* z: <chr>
* y: <chr>
* x: <chr>
* arg1: <chr>
* arg2: <chr>
> .Env$arg1
[1] "hey"
这会修改函数的主体,但可以通过 untrace 删除:
> body(myFun)
{
.doTrace(assign(".Env", environment(), .GlobalEnv))
{
x <- paste(arg1, arg2)
y <- paste(x, "hey")
z <- paste(y, "again!")
return(z)
}
}
> untrace(myFun)
> body(myFun)
{
x <- paste(arg1, arg2)
y <- paste(x, "hey")
z <- paste(y, "again!")
return(z)
}
>
更新 2: 总结一下,我们可以有一个函数来捕获另一个函数的环境,将其返回并将其写入磁盘以供进一步加载:
captureAndSave_functionEnv <- function (myFun, ...) {
trace(myFun, quote(assign(".myFun_env", environment(), .GlobalEnv)), print = FALSE)
#trace(myFun, quote({ untrace(myFun); assign(".myFun_env", environment(), parent.frame()) }), print = FALSE)
on.exit(untrace(myFun))
myFun(...)
saveRDS(.myFun_env, paste0(deparse(substitute(myFun)), ".rds"))
return(.myFun_env)
}
> captureAndSave_functionEnv(myFun)
<environment: 0x558f877eff20>
> myFun_env_loaded <- readRDS("myFun.rds")
> rlang::env_print(myFun_env_loaded)
<environment: 0x558f86d00890>
parent: <environment: global>
bindings:
* z: <chr>
* y: <chr>
* x: <chr>
* arg1: <chr>
* arg2: <chr>
> myFun_env_loaded$arg1
[1] "hey"
【问题讨论】:
标签: r function environment-variables