17.7 Quosures

  • Quosures bundles expression with an environment
  • Use enquo() instead of enexpr() (with eval_tidy())
with2 <- function(df, expr) {
  a <- 1000
  eval_tidy(enquo(expr), df)
}

df <- data.frame(x = 1:3)
a <- 10
with2(df, x + a)
#> [1] 11 12 13

“Whenever you use a data mask, you must always use enquo() instead of enexpr().

This comes back in Chapter 20.

17.7.1 Which environment is bundled?

  • The environment where the expression is created (i.e. the parent of where enquo() is called)

Here, the global environment

with2 <- function(df, expr) {
  a <- 1000
  eq <- enquo(expr)
  message("with2() Parent/Calling environment: ")
  print(rlang::caller_env())
  message("with2() environment: ")
  print(rlang::current_env())
  message("Quosure details: ")
  print(eq)  # Print the details of the quosure
  eval_tidy(eq, df)
}

a <- 10000
df <- data.frame(x = 1:3)
with2(df, x + a)
#> with2() Parent/Calling environment:
#> <environment: R_GlobalEnv>
#> with2() environment:
#> <environment: 0x560e510933c8>
#> Quosure details:
#> <quosure>
#> expr: ^x + a
#> env:  global
#> [1] 10001 10002 10003

Here, the fun1() environment

fun1 <- function(df) {
  a <- 10
  message("fun1() Parent/Calling environment: ")
  print(rlang::caller_env())
  message("fun1() environment: ")
  print(rlang::current_env())
  with2(df, x + a)
}

a <- 10000
df <- data.frame(x = 1:3)
fun1(df)
#> fun1() Parent/Calling environment:
#> <environment: R_GlobalEnv>
#> fun1() environment:
#> <environment: 0x560e54dac8c8>
#> with2() Parent/Calling environment:
#> <environment: 0x560e54dac8c8>
#> with2() environment:
#> <environment: 0x560e54aa7820>
#> Quosure details:
#> <quosure>
#> expr: ^x + a
#> env:  0x560e54dac8c8
#> [1] 11 12 13