% 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}}
}
}