Home > front end >  using `!!` without attaching `rlang`
using `!!` without attaching `rlang`

Time:03-25

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 unary and -.

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 
  • Related