Learning Objectives

Overview

Types of Expressions

Capturing Code

Evaluated versus Quoted Arguments

  • Evaluated arguments are those whose values are used. E.g. in sum(x), the x values are being used, but the variable name x is not.

  • Quoted arguments are those where the code is used. E.g. in library(rlang) we use the code rlang and not the value that rlang binds to.

  • Lots of dplyr functions use quoted arguments (where they use expressions in terms of variable names).

  • Exercise: Which are evaluated arguments and which are quoted arguments in the below function calls

    dplyr::filter(mtcars, mpg > 20, wt > 3)
    
    ggplot(mtcars, aes(x = wt, y = mpg)) +
      geom_point(col = "red")
    
    mtcars$mpg
    
    mtcars[["mpg"]]

Quosures

  • The {rlang} team made a new data object called a quosure (quoting closure) that bundles an expression with an environment. This makes it so that you do not have ambiguity when you evaluate an expression in a different environment where you have variable bindings.

  • E.g. the following is presents an issue of the user wanting a to be 10 but we have a being 1000.

    fun <- function(x) {
      a <- 1000
      x <- rlang::enexpr(x)
      eval(x)
    }
    a <- 10
    fun(a + 1)
    ## [1] 1001
  • Using rlang::enquo() will create a “quosure” which also includes the function environment. You cannot use base::eval() with a quosure, so {rlang} proves rlang::eval_tidy().

    fun <- function(x) {
      a <- 1000
      x <- rlang::enquo(x)
      rlang::eval_tidy(x)
    }
    a <- 10
    fun(a + 1)
    ## [1] 11
  • Quosures are mostly used when you use dots ... in a function argument and want to use that in conjunction with data masking (where you use a data frame like an environment). This is what most {dplyr} functions do. E.g. dplyr::filer() uses data masking with the .data like an environment and different predicates as the expressions. See the following help file for more information

    ?`topic-quosure`

Application: Capturing Argument Names

Application: Math Notation in Plots

Application: Using the tidyverse in a function

Application: Using dplyr-Style Code on New Classes.

Exercises

  1. Use rlang::call2() to create a call for table(x, y). Then remove the y component from that call to get table(x).

  2. stats::numericDeriv() requires an expression and an environment. Calculate the derivative of log(x) / sin(x) evaluated at x = 2

  3. You can calculate symbolic derivatives in R with D(), but you have to use expressions. Calculate the derivative of \(\sin(\cos(x + 1)^2)\). Then use that returned expression to evaluate the derivative at \(x =\) 1, 2, and 3.

  4. Create your own version of stopifnot() called stop_if_not(). E.g.:

    stop_if_not(1 == 1, 2 > 1)
    stop_if_not(1 == 0)
    ## Error: ~1 == 0 is not TRUE
    stop_if_not(c(1,2,3) == 2)
    ## Error: ~c(1, 2, 3) == 2 is not length 1
    stop_if_not("potato")
    ## Error in stop_if_not("potato"): ~"potato" is not a predicate
    • Note: The {assertthat} package explores this idea to the extreme.

New Functions


National Science Foundation Logo American University Logo Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.