Strange behaviour of enexpr()

I have been trying to get my head around the family of sym expr and quo functions and have come across some strange behaviour. In my example below, why does the order of execution of sym() and enexpr() matter?

library(rlang)

test_enexpr <- function(s1) {
  enexpr(s1)
}

test_sym <- function(s1) {
  sym(s1)
}

test_enexpr_sym <- function(s1) {
  list(enexpr(s1),
       sym(s1))
}

test_sym_enexpr <- function(s1) {
  list(sym(s1),
       enexpr(s1))
}

one <- "two"
test_enexpr(one)
#> one
test_sym(one)
#> two
test_enexpr_sym(one)
#> [[1]]
#> one
#> 
#> [[2]]
#> two
test_sym_enexpr(one)
#> [[1]]
#> two
#> 
#> [[2]]
#> [1] "two"

Created on 2020-06-25 by the reprex package (v0.3.0)

enexpr() quotes the argument supplied by the user of the function instead of evaluating it. Therefore, the function test_enexpr() returns the quoted expression one rather than the string "two".

sym() on the other hand, creates a symbol from a string. In this case, test_sym() evaluates the argument passed to it and converts the string "two" into the symbol two.

Given this context, the behaviour of test_enexpr_sym() is pretty easy to understand. The first element of the list is a quoted expression of the argument passed to s1 while the second element is the evaluated result of the variable one.

The last function is a bit tricky but I think what's happening here is that by calling sym() first, the object s1 has already been evaluated. So enexpr() sees the result of the evaluation (the string "two") and returns it as a quoted expression.

In general, you use sym(), expr() and quo() to capture expressions that you as the developer of the function supply whereas you use ensym(), enexpr() and enquo() to capture expressions that the users of your function supply.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.