One of the most intriguing things about R is its capability for metaprogramming: the idea that code is itself data, and can be inspected and modified programmatically. This is a powerful idea and deeply influences much R code. At a simple level it allows you to write
library(purrr) instead of
library("purrr") and enables
plot(x, sin(x)) to label the axes with
sin(x). At a deeper level it allows
y ~ x1 + x2 to represent a model that predicts the value of
subset(df, x == y) to be translated to
df[df$x == df$y, , drop = FALSE], and
dplyr::filter(db, is.na(x)) to generate the SQL
WHERE x IS NULL when
db is a remote database table.
Closely related to metaprogramming is non-standard evaluation, or NSE for short. This term is commonly used to describe the behaviour of R functions, but there are two problems with it. Firstly, NSE is actually a property of an argument (or arguments) of a function, so talking about NSE functions is a little sloppy. Secondly, it’s confusing to define something by what it is not (standard), so in this book I’ll teach you more precise vocabulary.
Specifically, this book focuses on tidy evaluation (sometimes called tidy eval for short). Tidy evaluation is implemented in the rlang package (Henry and Wickham 2018b), and I’ll use rlang extensively in these chapters. This will allow you to focus on the big ideas, without being distracted by implementation quirks that arise from R’s history. After I introduce each big idea with rlang, I’ll then circle back to talk about how those ideas are expressed in base R. This approach seems backward to some, but it’s analogous to learning how to drive an automatic transmission before a manual one so you can focus on the big picture before learning the details. This book focusses on the theoretical side of tidy evaluation, so you can fully understand how it works from the ground up. If you are looking for a practical introduction, I recommend the “tidy evaluation book”, https://tidyeval.tidyverse.org57.
You’ll learn about metaprogramming and tidy evaluation in the following five chapters:
In Big picture, Chapter 17, you’ll get a glimpse of the whole metaprogramming story, briefly learning about each of the major components and how they fit together into a cohesive whole.
In Expressions, Chapter 18, you’ll learn that all R code can be described as a tree. You’ll learn how to visualise that tree, how the rules of R’s grammar convert linear sequences of characters into a tree, and how to use recursive functions to work with code trees.
In Quasiquotation, Chapter 19, you’ll learn to use tools from rlang to capture (“quote”) unevaluated function arguments. You’ll also learn about quasiquotation, which provides a set of techniques for “unquoting” input that makes it possible to easily generate new trees from code fragments.
In Evaluation, Chapter 20, you’ll learn how to evaluate captured code. Here you’ll learn about an important data structure, the quosure, which ensures correct evaluation by capturing both the code to evaluate, and the environment in which to evaluate it. This chapter will show you how to put all the pieces together to understand how NSE in base R works, and how to write your own functions that work like
Finally, in Translating R code, Chapter 21, you’ll see how to combine first-class environments, lexical scoping, and metaprogramming to translate R code into other languages, namely HTML and LaTeX.
Henry, Lionel, and Hadley Wickham. 2018b. Rlang: Tools for Low-Level R Programming. https://rlang.r-lib.org.
The tidy evaluation book is a work-in-progress at the time I wrote this chapter, but will hopefully be finished by the time you read it.↩