使用 rlang::eval_tidy 时理解赋值
Understanding assignment when using 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
赋值给new_env
里面的x
。
现在,我们使用 base::eval
来计算这个表达式:
eval(x_expr, envir = new_env)
get('x', envir = new_env)
这个returns1
。如果我们简单地在全局环境中评估 x
,我们会得到一个错误(表明 x
在 new_env
中而不是从全局环境中获取)。
我们可以从 new_env
中删除 x
,然后使用 rlang::eval_bare
:
重新分配它
rm('x', envir = new_env)
rlang::eval_bare(x_expr, env = new_env)
get('x', envir = new_env)
同样,这给出 1
。
现在,我们再次从 new_env
中删除 x
,并尝试使用 rlang::eval_tidy
重新分配它。但是,在这种情况下,当我们在 new_env
:
中查找 x
时会出错
rm('x', envir = new_env)
rlang::eval_tidy(x_expr, env = new_env)
get('x', 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()
always evaluates in a data mask, even when data is NULL
. Because of this, it has different stack semantics than base::eval()
:
- Lexical side effects, such as assignment with
<-
, occur in the mask rather than 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
我想了解为什么在使用 rlang::eval_tidy
评估 <-
赋值操作时会发生以下情况。
让我们使用 rlang::expr
创建一个表达式来为变量 x
赋值 1。
x_expr <- rlang::expr(x <- 1)
我们还创建了一个要在其中计算表达式的环境。
new_env <- new.env(parent = parent.env(environment()))
我的意图是将1
赋值给new_env
里面的x
。
现在,我们使用 base::eval
来计算这个表达式:
eval(x_expr, envir = new_env)
get('x', envir = new_env)
这个returns1
。如果我们简单地在全局环境中评估 x
,我们会得到一个错误(表明 x
在 new_env
中而不是从全局环境中获取)。
我们可以从 new_env
中删除 x
,然后使用 rlang::eval_bare
:
rm('x', envir = new_env)
rlang::eval_bare(x_expr, env = new_env)
get('x', envir = new_env)
同样,这给出 1
。
现在,我们再次从 new_env
中删除 x
,并尝试使用 rlang::eval_tidy
重新分配它。但是,在这种情况下,当我们在 new_env
:
x
时会出错
rm('x', envir = new_env)
rlang::eval_tidy(x_expr, env = new_env)
get('x', 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()
always evaluates in a data mask, even when data isNULL
. Because of this, it has different stack semantics thanbase::eval()
:
- Lexical side effects, such as assignment with
<-
, occur in the mask rather thanenv
.
我们可以通过在 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