I'm writing a package and one of my functions generates a ggplot. I would like to only import ggplot2 or rlang (without depending on them). After some trial and error I managed to get it to work, but now I'm not sure why it works.
So my question is, why does the following code work without directly accessing !!
with ::
?
arg1 <- "Species"
ggplot2::ggplot(iris, ggplot2::aes(x = Petal.Width, y = !!rlang::sym(arg1)))
ggplot2::geom_bar(stat = "summary", fun = "max")
My understanding is that in order to access the !!
function I should have to specify the package with ::
, but this example works so what am I missing?
CodePudding user response:
It works because ‘rlang’/tidy evaluation doesn’t actually resolve the !!
operator, it doesn’t even define such an operator — and in fact this operator doesn’t even exist! It’s just two chained !
operators which never get evaluated because tidy evaluation uses non-standard evaluation.
So even if you wanted to you couldn’t import or attach a !!
operator.
CodePudding user response:
If the rlang
package is loaded (or even the ggplot2 package is loaded), then using help("!!")
brings up a help page naming this as the "injection operator" that suggests Konrad Rudolph's answer is wrong or at least out-of-sync with the Hadley's version of NSE parlance. The link given in a comment to Konrad's answer is more helpful: https://adv-r.hadley.nz/quasiquotation.html#the-polite-fiction-of. (Konrad being wrong would be a highly unusual instance.) The "injection operator" as it's called there, is also mentioned on `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 unaryand
-
.
In the current instance you can also get the same result with "! ! "
, which I found odd but is explained by the "polite-fiction" material.
My suspicion is that the simple act of calling ggplot2::ggplot
will load a bunch of required packages into the accessible set of Namespaces even though you tried to prevent that by using the "::" method. So the "!!" does get evaluated in the NSE manner despite efforts to prevent that occurring:
#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