% Generated by roxygen2: do not edit by hand % Please edit documentation in R/nse-inject.R \name{injection-operator} \alias{injection-operator} \alias{bang-bang} \alias{!!} \title{Injection operator \verb{!!}} \description{ The \link[=topic-inject]{injection} operator \verb{!!} injects a value or expression inside another expression. In other words, it modifies a piece of code before R evaluates it. There are two main cases for injection. You can inject constant values to work around issues of \link[=topic-data-mask-ambiguity]{scoping ambiguity}, and you can inject \link[=topic-defuse]{defused expressions} like \link[=sym]{symbolised} column names. } \section{Where does \verb{!!} work?}{ \verb{!!} does not work everywhere, you can only use it within certain special functions: \itemize{ \item Functions taking \link[=topic-defuse]{defused} and \link[=topic-data-mask]{data-masked} arguments. Technically, this means function arguments defused with \ifelse{html}{\code{\link[=embrace-operator]{\{\{}}}{\verb{\{\{}} or \code{en}-prefixed operators like \code{\link[=enquo]{enquo()}}, \code{\link[=enexpr]{enexpr()}}, etc. \item Inside \code{\link[=inject]{inject()}}. } All data-masking verbs in the tidyverse support injection operators out of the box. With base functions, you need to use \code{\link[=inject]{inject()}} to enable \verb{!!}. Using \verb{!!} out of context may lead to incorrect results, see \ifelse{html}{\link[=topic-inject-out-of-context]{What happens if I use injection operators out of context?}}{\link[=topic-inject-out-of-context]{What happens if I use injection operators out of context?}}. The examples below are built around the base function \code{\link[=with]{with()}}. Since it's not a tidyverse function we will use \code{\link[=inject]{inject()}} to enable \verb{!!} usage. } \section{Injecting values}{ Data-masking functions like \code{\link[=with]{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): \if{html}{\out{
}}\preformatted{cyl <- c(100, 110) with(mtcars, mean(cyl)) #> [1] 6.1875 }\if{html}{\out{
}} The injection operator offers one way of solving this. Use it to inject the env-variable inside the data-masked expression: \if{html}{\out{
}}\preformatted{inject( with(mtcars, mean(!!cyl)) ) #> [1] 105 }\if{html}{\out{
}} Note that the \code{\link{.env}} pronoun is a simpler way of solving the ambiguity. See \ifelse{html}{\link[=topic-data-mask-ambiguity]{The data mask ambiguity}}{\link[=topic-data-mask-ambiguity]{The data mask ambiguity}} for more about this. } \section{Injecting expressions}{ Injection is also useful for modifying parts of a \link[=topic-defuse]{defused expression}. In the following example we use the \link[=topic-metaprogramming]{symbolise-and-inject pattern} to inject a column name inside a data-masked expression. \if{html}{\out{
}}\preformatted{var <- sym("cyl") inject( with(mtcars, mean(!!var)) ) #> [1] 6.1875 }\if{html}{\out{
}} Since \code{\link[=with]{with()}} is a base function, you can't inject \link[=topic-quosure]{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. } \section{When do I need \verb{!!}?}{ With tidyverse APIs, injecting expressions with \verb{!!} is no longer a common pattern. First, the \code{\link{.env}} pronoun solves the ambiguity problem in a more intuitive way: \if{html}{\out{
}}\preformatted{cyl <- 100 mtcars \%>\% dplyr::mutate(cyl = cyl * .env$cyl) }\if{html}{\out{
}} Second, the embrace operator \ifelse{html}{\code{\link[=embrace-operator]{\{\{}}}{\verb{\{\{}} makes the \link[=topic-metaprogramming]{defuse-and-inject pattern} easier to learn and use. \if{html}{\out{
}}\preformatted{my_mean <- function(data, var) \{ data \%>\% dplyr::summarise(mean(\{\{ var \}\})) \} # Equivalent to my_mean <- function(data, var) \{ data \%>\% dplyr::summarise(mean(!!enquo(var))) \} }\if{html}{\out{
}} \verb{!!} is a good tool to learn for advanced applications but our hope is that it isn't needed for common data analysis cases. } \seealso{ \itemize{ \item \ifelse{html}{\link[=topic-inject]{Injecting with !!, !!!, and glue syntax}}{\link[=topic-inject]{Injecting with !!, !!!, and glue syntax}} \item \ifelse{html}{\link[=topic-metaprogramming]{Metaprogramming patterns}}{\link[=topic-metaprogramming]{Metaprogramming patterns}} } }