18.1 Introduction

To compute on the language, we first need to understand its structure.

  • This requires a few things:
    • New vocabulary.
    • New tools to inspect and modify expressions.
    • Approach the use of the language with new ways of thinking.
  • One of the first new ways of thinking is the distinction between an operation and its result.
y <- x * 10
#> Error in x * 10: non-numeric argument to binary operator
  • We can capture the intent of the code without executing it using the rlang package.
z <- rlang::expr(y <- x * 10)

z
#> y <- x * 10
  • We can then evaluate the expression using the base::eval function.
x <- 4

base::eval(expr(y <- x * 10))

y
#> [1] 40

18.1.1 Evaluating multiple expressions

  • The function expression() allows for multiple expressions, and in some ways it acts similarly to the way files are source()d in. That is, we eval()uate all of the expressions at once.

  • expression() returns a vector and can be passed to eval().

z <- expression(x <- 4, x * 10)

eval(z)
#> [1] 40
is.atomic(z)
#> [1] FALSE
is.vector(z)
#> [1] TRUE
  • exprs() does not evaluate everything at once. To evaluate each expression, the individual expressions must be evaluated in a loop.
for (i in exprs(x <- 4, x * 10)) {
print(i)
print(eval(i))
}
#> x <- 4
#> [1] 4
#> x * 10
#> [1] 40