使用 rlang::eval_tidy 时理解赋值

问题描述

我想了解为什么在使用 <- 评估 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,我们会得到一个错误(表明 xnew_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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...