quasiquotation {rlang}R Documentation

Quasiquotation of an expression

Description

Quasiquotation is the mechanism that makes it possible to program flexibly with tidy evaluation grammars like dplyr. It is enabled in all tidyeval quoting functions, the most fundamental of which are quo() and expr().

Quasiquotation is the combination of quoting an expression while allowing immediate evaluation (unquoting) of part of that expression. We provide both syntactic operators and functional forms for unquoting.

Use qq_show() to experiment with quasiquotation or debug the effect of unquoting operators. qq_show() quotes its input, processes unquoted parts, and prints the result with expr_print(). This expression printer has a clearer output than the base R printer (see the documentation topic).

Usage

UQ(x)

UQE(x)

UQS(x)

"!!"(x)

":="(x, y)

qq_show(expr)

Arguments

x

An expression to unquote.

y

An R expression that will be given the argument name supplied to x.

expr

An expression to be quasiquoted.

Unquoting names

When a function takes multiple named arguments (e.g. dplyr::mutate()), it is difficult to supply a variable as name. Since the LHS of = is quoted, giving the name of a variable results in the argument having the name of the variable rather than the name stored in that variable. This problem is right up the alley for the unquoting operator !!. If you were able to unquote the variable when supplying the name, the argument would be named after the content of that variable.

Unfortunately R is very strict about the kind of expressions supported on the LHS of =. This is why we have made the more flexible := operator an alias of =. You can use it to supply names, e.g. a := b is equivalent to a = b. Since its syntax is more flexible you can unquote on the LHS:

name <- "Jane"

dots_list(!!name := 1 + 2)
exprs(!!name := 1 + 2)
quos(!!name := 1 + 2)

Like =, the := operator expects strings or symbols on its LHS.

Theory

Formally, quo() and expr() are quasiquote functions, !! is the unquote operator, and !!! is the unquote-splice operator. These terms have a rich history in Lisp languages, and live on in modern languages like Julia and Racket.

Life cycle

Examples

# Quasiquotation functions quote expressions like base::quote()
quote(how_many(this))
expr(how_many(this))
quo(how_many(this))

# In addition, they support unquoting. Let's store symbols
# (i.e. object names) in variables:
this <- sym("apples")
that <- sym("oranges")

# With unquotation you can insert the contents of these variables
# inside the quoted expression:
expr(how_many(!!this))
expr(how_many(!!that))

# You can also insert values:
expr(how_many(!!(1 + 2)))
quo(how_many(!!(1 + 2)))


# Note that when you unquote complex objects into an expression,
# the base R printer may be a bit misleading. For anstance compare
# the output of `expr()` and `quo()` (which uses a custom printer)
# when we unquote an integer vector:
expr(how_many(!!(1:10)))
quo(how_many(!!(1:10)))

# This is why it's often useful to use qq_show() to examine the
# result of unquotation operators. It uses the same printer as
# quosures but does not return anything:
qq_show(how_many(!!(1:10)))


# Use `!!!` to add multiple arguments to a function. Its argument
# should evaluate to a list or vector:
args <- list(1:3, na.rm = TRUE)
quo(mean(!!!args))

# You can combine the two
var <- quote(xyz)
extra_args <- list(trim = 0.9, na.rm = TRUE)
quo(mean(!!var , !!!extra_args))


# The plural versions have support for the `:=` operator.
# Like `=`, `:=` creates named arguments:
quos(mouse1 := bernard, mouse2 = bianca)

# The `:=` is mainly useful to unquote names. Unlike `=` it
# supports `!!` on its LHS:
var <- "unquote me!"
quos(!!var := bernard, mouse2 = bianca)


# All these features apply to dots captured by enquos():
fn <- function(...) enquos(...)
fn(!!! args, !!var := penny)


# Unquoting is especially useful for building an expression by
# expanding around a variable part (the unquoted part):
quo1 <- quo(toupper(foo))
quo1

quo2 <- quo(paste(!!quo1, bar))
quo2

quo3 <- quo(list(!!quo2, !!!syms(letters[1:5])))
quo3

[Package rlang version 0.2.2 Index]