问题描述
我想了解为什么在使用 <-
评估 rlang::eval_tidy
赋值操作时会发生以下情况。
让我们使用 rlang::expr
创建一个表达式来为变量 x
赋值 1。
x_expr <- rlang::expr(x <- 1)
我们还创建了一个环境来评估表达式。
new_env <- new.env(parent = parent.env(environment()))
我的意图是我们将 1
分配给 x
内的 new_env
。
现在,我们使用 base::eval
来评估这个表达式:
eval(x_expr,envir = new_env)
get('x',envir = new_env)
这将返回 1
。如果我们只是在全局环境中计算 x
,我们会得到一个错误(表明 x
在 new_env
中而不是从全局环境中获取)。
我们可以从 x
中删除 new_env
,然后使用 rlang::eval_bare
重新分配它:
rm('x',envir = new_env)
rlang::eval_bare(x_expr,env = new_env)
get('x',envir = new_env)
同样,这给出了 1
。
现在,我们再次从 x
中删除 new_env
,并尝试使用 rlang::eval_tidy
重新分配它。但是,在这种情况下,当我们在 x
中查找 new_env
时会得到一个错误:
rm('x',envir = new_env)
rlang::eval_tidy(x_expr,envir = new_env)
为什么会这样?我认为 x
已分配给 1
,但在哪里?
sessionInfo()
:
R version 4.1.0 (2021-05-18)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19042)
Matrix products: default
locale:
[1] LC_COLLATE=English_South Africa.1252 LC_CTYPE=English_South Africa.1252
[3] LC_MONETARY=English_South Africa.1252 LC_NUMERIC=C
[5] LC_TIME=English_South Africa.1252
attached base packages:
[1] stats graphics Grdevices utils datasets methods base
loaded via a namespace (and not attached):
[1] compiler_4.1.0 tools_4.1.0 yaml_2.2.1 rlang_0.4.11
解决方法
从 eval_tidy()
的 documentation:
eval_tidy()
始终在数据掩码中求值,即使数据为 NULL
。因此,它具有与 base::eval()
:
- 词法副作用,例如使用
<-
赋值,出现在掩码中而不是env
中。
我们可以通过在 tidy_eval()
library(rlang)
x_expr <- rlang::expr(x <- 1)
new_env <- new.env(parent = parent.env(environment()))
data_mask <- rlang::new_data_mask(new.env(parent = parent.env(environment())))
rlang::eval_tidy(x_expr,data_mask,env = new_env)
get('x',envir = data_mask) ## Returns 1