The injection operator
!! injects a value or
expression inside another expression. In other words, it modifies a
piece of code before R evaluates it.
!! does not work everywhere, you can only use it within certain
All data-masking verbs in the tidyverse support injection operators
out of the box. With base functions, you need to use
!! out of context may lead to incorrect
results, see What happens if I use injection operators out of context?.
Data-masking functions like
with() are handy because you can
refer to column names in your computations. This comes at the price
of data mask ambiguity: if you have defined an env-variable of the
same name as a data-variable, you get a name collisions. This
collision is always resolved by giving precedence to the
data-variable (it masks the env-variable):
The injection operator offers one way of solving this. Use it to inject the env-variable inside the data-masked expression:
with() is a base function, you can't inject
quosures, only naked symbols and calls. This
isn't a problem here because we're injecting the name of a data
frame column. If the environment is important, try injecting a
pre-computed value instead.
With tidyverse APIs, injecting expressions with
!! is no longer a
common pattern. First, the
.env pronoun solves the
ambiguity problem in a more intuitive way:
cyl <- 100 mtcars %>% dplyr::mutate(cyl = cyl * .env$cyl)
!! is a good tool to learn for advanced applications but our
hope is that it isn't needed for common data analysis cases.