enquo()
and enquos()
defuse function arguments.
A defused expression can be examined, modified, and injected into
other expressions.
Defusing function arguments is useful for:
Creating data-masking functions.
Interfacing with another data-masking function using the defuse-and-inject pattern.
These are advanced tools. Make sure to first learn about the embrace
operator {{
in Data mask programming patterns.
{{
is easier to work with less theory, and it is sufficient
in most applications.
Arguments
- arg
An unquoted argument name. The expression supplied to that argument is defused and returned.
- ...
Names of arguments to defuse.
- .named
If
TRUE
, unnamed inputs are automatically named withas_label()
. This is equivalent to applyingexprs_auto_name()
on the result. IfFALSE
, unnamed elements are left as is and, if fully unnamed, the list is given minimal names (a vector of""
). IfNULL
, fully unnamed results are left withNULL
names.- .ignore_empty
Whether to ignore empty arguments. Can be one of
"trailing"
,"none"
,"all"
. If"trailing"
, only the last argument is ignored if it is empty. Named arguments are not considered empty.- .ignore_null
Whether to ignore unnamed null arguments. Can be
"none"
or"all"
.- .unquote_names
Whether to treat
:=
as=
. Unlike=
, the:=
syntax supports names injection.- .homonyms
How to treat arguments with the same name. The default,
"keep"
, preserves these arguments. Set.homonyms
to"first"
to only keep the first occurrences, to"last"
to keep the last occurrences, and to"error"
to raise an informative error and indicate what arguments have duplicated names.- .check_assign
Whether to check for
<-
calls. WhenTRUE
a warning recommends users to use=
if they meant to match a function parameter or wrap the<-
call in curly braces otherwise. This ensures assignments are explicit.
Implicit injection
Arguments defused with enquo()
and enquos()
automatically gain
injection support.
my_mean <- function(data, var) {
var <- enquo(var)
dplyr::summarise(data, mean(!!var))
}
# Can now use `!!` and `{{`
my_mean(mtcars, !!sym("cyl"))
See enquo0()
and enquos0()
for variants that don't enable
injection.
See also
Defusing R expressions for an overview.
expr()
to defuse your own local expressions.base::eval()
andeval_bare()
for resuming evaluation of a defused expression.
Examples
# `enquo()` defuses the expression supplied by your user
f <- function(arg) {
enquo(arg)
}
f(1 + 1)
#> <quosure>
#> expr: ^1 + 1
#> env: 0x562ec119a4c8
# `enquos()` works with arguments and dots. It returns a list of
# expressions
f <- function(...) {
enquos(...)
}
f(1 + 1, 2 * 10)
#> <list_of<quosure>>
#>
#> [[1]]
#> <quosure>
#> expr: ^1 + 1
#> env: 0x562ec119a4c8
#>
#> [[2]]
#> <quosure>
#> expr: ^2 * 10
#> env: 0x562ec119a4c8
#>
# `enquo()` and `enquos()` enable _injection_ and _embracing_ for
# your users
g <- function(arg) {
f({{ arg }} * 2)
}
g(100)
#> <list_of<quosure>>
#>
#> [[1]]
#> <quosure>
#> expr: ^(^100) * 2
#> env: 0x562ec0a780e0
#>
column <- sym("cyl")
g(!!column)
#> <list_of<quosure>>
#>
#> [[1]]
#> <quosure>
#> expr: ^(^cyl) * 2
#> env: 0x562ec0693588
#>