>#R version 3.1.1 (2014-07-10) -- "Sock it to Me"
> library(pryr)
> f1 <- function() { cat("hi1\n"); 1 }
> f2 <- function() { cat("hi2\n"); 2 }
这是我想要的,但e
= globalenv
:
> e <- new.env()
> delayedAssign("x", f1(), assign.env = e)
> substitute(x, e)
f1()
如果我尝试substitute
它不起作用(根据文档,substitute
中没有globalenv
):
> delayedAssign("x", f1(), assign.env = globalenv())
> substitute(x, globalenv())
x
来自subs
的 pryr
无法正常工作,因为它会评估承诺:
> subs(x, globalenv())
hi1
[1] 1
实际上它会评估所有承诺,因为它会将globalenv
转换为列表:
> delayedAssign("x", f1(), assign.env = globalenv())
> delayedAssign("y", f2(), assign.env = globalenv())
> subs(x, globalenv())
hi1
hi2
[1] 1
>
总结:是否有可能在substitute
等所有环境中都使用globalenv
这样的承诺?
更新
我无法弄清楚如何在R中做到这一点,所以我写了(更确切地说是从R代码中提取)以下C函数
SEXP get_no_eval(SEXP symbol, SEXP envir) {
SEXP t;
if (!Rf_isString(symbol) || Rf_length(symbol)!=1)
Rf_error("symbol is not a string");
if (!Rf_isEnvironment(envir))
Rf_error("envir is not an environment");
if (envir==R_NilValue)
Rf_error("envir is NULL");
t = Rf_findVar(Rf_install(CHAR(STRING_ELT(symbol, 0))), envir);
if (t != R_UnboundValue) {
if (TYPEOF(t) == PROMSXP) {
do {
t = PREXPR(t);
} while(TYPEOF(t) == PROMSXP);
if (NAMED(t) < 2) SET_NAMED(t, 2);
return t;
}
else if (TYPEOF(t) == DOTSXP)
Rf_error("'...' used in an incorrect context");
return t;
}
Rf_error("symbol not found");
return R_NilValue;
}
现在,我可以继续上面的例子:
> delayedAssign("x", f1(), assign.env = globalenv())
> get_no_eval("x", globalenv())
f1()
不完全是substitute
,但可以满足我的需要。