使用 `!!` 而不附加 `rlang`
using `!!` without attaching `rlang`
我正在写一个包,我的一个函数生成了一个 ggplot。我只想导入 ggplot2 或 rlang(不依赖于它们)。经过一些尝试和错误后,我设法让它工作,但现在我不确定为什么它能工作。
所以我的问题是,为什么下面的代码可以在不使用 ::
直接访问 !!
的情况下工作?
arg1 <- "Species"
ggplot2::ggplot(iris, ggplot2::aes(x = Petal.Width, y = !!rlang::sym(arg1))) +
ggplot2::geom_bar(stat = "summary", fun = "max")
我的理解是,为了访问 !!
函数,我必须使用 ::
指定包,但是这个示例有效,所以我缺少什么?
之所以有效,是因为“rlang”/tidy 求值实际上并没有解析 !!
运算符,它甚至没有 define 这样的运算符——事实上这个运算符甚至 不存在! 它只是两个链式 !
运算符,它们永远不会被评估,因为整洁的评估使用 non-standard evaluation。 “rlang”中的实际实现是在 C++ 中,修复 R 运算符优先级规则中的不匹配相当复杂,但功能子集的简化版本可能如下所示:
bang = as.name('!')
interpolate_bang_bang = function (expr, envir) {
if (is.call(expr) && expr[[1L]] == bang) {
if (is.call(expr[[2L]]) && expr[[2L]][[1L]] == bang) {
eval(expr[[2L]][[2L]], envir = envir)
} else {
expr
}
} else {
expr
}
}
这会测试未评估的表达式是否恰好是 !! ‹something›
,并将其替换为 ‹something›
的评估版本。真正的实现要复杂得多,因为它需要处理任意复杂的嵌套表达式(例如 1 + !!x
),而且它还要做很多其他事情。但上面说明了基本事实:没有 !!
运算符。相反,“rlang”检查未评估的表达式是否包含两个立即嵌套的 !
运算符调用。
因此,即使您愿意,也无法导入或附加 !!
运算符。
如果加载了 rlang
包(或者甚至加载了 ggplot2 包),那么使用 help("!!")
会打开一个帮助页面,将其命名为“注入运算符”,建议 Konrad Rudolph 的回答错误 或至少 out-of-sync 哈德利版本的 NSE 说法。对 Konrad 的回答的评论中给出的 link 更有帮助:https://adv-r.hadley.nz/quasiquotation.html#the-polite-fiction-of。 (Konrad 的错误将是一个非常不寻常的例子。)“注入运算符”,因为它在那里被称为,也在 `help("topic-inject-out-of-context").
中提到。
!!
and !!!
behave specially inside all quoting functions powered by rlang, where they behave like real operators with precedence equivalent to unary +
and -
.
在当前实例中,您也可以使用 "! ! "
获得相同的结果,我觉得这很奇怪,但可以用“polite-fiction”来解释 material.
我怀疑调用 ggplot2::ggplot
的简单行为会将一堆必需的包加载到可访问的命名空间集中,即使您试图通过使用“::”方法来阻止这种情况。所以 ”!!”尽管努力防止这种情况发生,但确实以 NSE 方式进行评估:
#In an entirely base session with only required packages loaded ....
ggplot2::ggplot(iris, ggplot2::aes(x = Petal.Width))
#-----------------------------------
> sessionInfo()
R version 4.1.2 (2021-11-01)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.5 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] magrittr_2.0.2 tidyselect_1.1.2 munsell_0.5.0 colorspace_2.0-3 R6_2.5.1 rlang_1.0.2
[7] fansi_1.0.2 dplyr_1.0.8 tools_4.1.2 grid_4.1.2 gtable_0.3.0 utf8_1.2.2
[13] cli_3.2.0 DBI_1.1.2 ellipsis_0.3.2 assertthat_0.2.1 digest_0.6.29 tibble_3.1.6
[19] lifecycle_1.0.1 crayon_1.5.0 purrr_0.3.4 ggplot2_3.3.5 vctrs_0.3.8 glue_1.6.2
[25] labeling_0.4.2 compiler_4.1.2 pillar_1.7.0 generics_0.1.2 scales_1.1.1 pkgconfig_2.0.3
我正在写一个包,我的一个函数生成了一个 ggplot。我只想导入 ggplot2 或 rlang(不依赖于它们)。经过一些尝试和错误后,我设法让它工作,但现在我不确定为什么它能工作。
所以我的问题是,为什么下面的代码可以在不使用 ::
直接访问 !!
的情况下工作?
arg1 <- "Species"
ggplot2::ggplot(iris, ggplot2::aes(x = Petal.Width, y = !!rlang::sym(arg1))) +
ggplot2::geom_bar(stat = "summary", fun = "max")
我的理解是,为了访问 !!
函数,我必须使用 ::
指定包,但是这个示例有效,所以我缺少什么?
之所以有效,是因为“rlang”/tidy 求值实际上并没有解析 !!
运算符,它甚至没有 define 这样的运算符——事实上这个运算符甚至 不存在! 它只是两个链式 !
运算符,它们永远不会被评估,因为整洁的评估使用 non-standard evaluation。 “rlang”中的实际实现是在 C++ 中,修复 R 运算符优先级规则中的不匹配相当复杂,但功能子集的简化版本可能如下所示:
bang = as.name('!')
interpolate_bang_bang = function (expr, envir) {
if (is.call(expr) && expr[[1L]] == bang) {
if (is.call(expr[[2L]]) && expr[[2L]][[1L]] == bang) {
eval(expr[[2L]][[2L]], envir = envir)
} else {
expr
}
} else {
expr
}
}
这会测试未评估的表达式是否恰好是 !! ‹something›
,并将其替换为 ‹something›
的评估版本。真正的实现要复杂得多,因为它需要处理任意复杂的嵌套表达式(例如 1 + !!x
),而且它还要做很多其他事情。但上面说明了基本事实:没有 !!
运算符。相反,“rlang”检查未评估的表达式是否包含两个立即嵌套的 !
运算符调用。
因此,即使您愿意,也无法导入或附加 !!
运算符。
如果加载了 rlang
包(或者甚至加载了 ggplot2 包),那么使用 help("!!")
会打开一个帮助页面,将其命名为“注入运算符”,建议 Konrad Rudolph 的回答错误 或至少 out-of-sync 哈德利版本的 NSE 说法。对 Konrad 的回答的评论中给出的 link 更有帮助:https://adv-r.hadley.nz/quasiquotation.html#the-polite-fiction-of。 (Konrad 的错误将是一个非常不寻常的例子。)“注入运算符”,因为它在那里被称为,也在 `help("topic-inject-out-of-context").
!!
and!!!
behave specially inside all quoting functions powered by rlang, where they behave like real operators with precedence equivalent to unary+
and-
.
在当前实例中,您也可以使用 "! ! "
获得相同的结果,我觉得这很奇怪,但可以用“polite-fiction”来解释 material.
我怀疑调用 ggplot2::ggplot
的简单行为会将一堆必需的包加载到可访问的命名空间集中,即使您试图通过使用“::”方法来阻止这种情况。所以 ”!!”尽管努力防止这种情况发生,但确实以 NSE 方式进行评估:
#In an entirely base session with only required packages loaded ....
ggplot2::ggplot(iris, ggplot2::aes(x = Petal.Width))
#-----------------------------------
> sessionInfo()
R version 4.1.2 (2021-11-01)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 18.04.5 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/libopenblasp-r0.2.20.so
locale:
[1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
loaded via a namespace (and not attached):
[1] magrittr_2.0.2 tidyselect_1.1.2 munsell_0.5.0 colorspace_2.0-3 R6_2.5.1 rlang_1.0.2
[7] fansi_1.0.2 dplyr_1.0.8 tools_4.1.2 grid_4.1.2 gtable_0.3.0 utf8_1.2.2
[13] cli_3.2.0 DBI_1.1.2 ellipsis_0.3.2 assertthat_0.2.1 digest_0.6.29 tibble_3.1.6
[19] lifecycle_1.0.1 crayon_1.5.0 purrr_0.3.4 ggplot2_3.3.5 vctrs_0.3.8 glue_1.6.2
[25] labeling_0.4.2 compiler_4.1.2 pillar_1.7.0 generics_0.1.2 scales_1.1.1 pkgconfig_2.0.3