One of the most intriguing things about R is its ability to do metaprogramming. This is the idea that code is data that can be inspected and modified programmatically. This is a powerful idea; one that deeply influences much R code. At the most basic level, it allows you to do things like write
library(purrr) instead of
library("purrr") and enable
plot(x, sin(x)) to automatically label the axes with
sin(x). At a deeper level, it allows you to do things like use
y ~ x1 + x2 to represent a model that predicts the value of
x2, to translate
subset(df, x == y) into
df[df$x == df$y, , drop = FALSE], and to use
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, NSE for short. This term, which is commonly used to describe the behaviour of R functions, is problematic in two ways. Firstly, NSE is actually a property of the 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’s not (standard), so in this book I’ll introduce 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 the quirks of implementation 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 may seem backward to some, but it’s like learning how to drive using an automatic transmission rather than a stick shift: it allows you to focus on the big picture before having to learn 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 more practical introduction, I recommend the tidy evaluation book at https://tidyeval.tidyverse.org57.
You’ll learn about metaprogramming and tidy evaluation in the following five chapters:
Chapter 17 gives a high level description of the whole metaprogramming story, briefly learning about all major components and how they fit together to form a cohesive whole.
Chapter 18 shows that that all R code can be described as a tree. You’ll learn how to visualise these trees, how the rules of R’s grammar convert linear sequences of characters into these trees, and how to use recursive functions to work with code trees.
Chapter 19 presents tools from rlang that you can use to capture (quote) unevaluated function arguments. You’ll also learn about quasiquotation, which provides a set of techniques to unquote input to make it possible to easily generate new trees from code fragments.
Chapter 20 moves on to evaluating 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 works in base R, and how to write functions that work like
Chapter 21 finishes up by combining 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.
As I write this chapter, the tidy evaluation book is still a work-in-progress, but by the time you read this it will hopefully be finished.↩