Skip to content

Instantly share code, notes, and snippets.

@steve-liang
Last active July 7, 2019 20:03
Show Gist options
  • Select an option

  • Save steve-liang/31597d8c909f923e2c4fc3f9dcb56b57 to your computer and use it in GitHub Desktop.

Select an option

Save steve-liang/31597d8c909f923e2c4fc3f9dcb56b57 to your computer and use it in GitHub Desktop.
Gist for Twitter's Troubleshooting substitute() vs. enquo()
my_summarise() is a custom function that automatically choose between sym() and enquo() for input type "character" and ^quosure
## This works!
my_summarise <- function(df, var){
if(inherits(substitute(var), "character")){
var = sym(var)
}
else if(inherits(substitute(var), "name")){
var = enquo(var)
}
df %>% summarise(avg = mean(!!var))
}
identical(my_summarise(iris, Sepal.Length),
my_summarise(iris, 'Sepal.Length'))
# TRUE
######################
## Thought substitute() was equivalent to enquo() but it's not. Replacing substitute() with enquo()
my_summarise2 <- function(df, var){
if(inherits(enquo(var), "character")){
var = sym(var)
}
else if(inherits(enquo(var), "name")){
var = enquo(var)
}
df %>% summarise(avg = mean(!!var))
}
identical(my_summarise2(iris, Sepal.Length),
my_summarise2(iris, 'Sepal.Length'))
# object 'Sepal.Length' not found
#####################
## Replacing enquo() with enexpr() WORKS !
my_summarise3 <- function(df, var){
if(inherits(enexpr(var), "character")){
var = sym(var)
}
else if(inherits(enexpr(var), "name")){
var = enquo(var)
}
df %>% summarise(avg = mean(!!var))
}
identical(my_summarise3(iris, Sepal.Length),
my_summarise3(iris, 'Sepal.Length'))
# TRUE
@steve-liang
Copy link
Author

For anyone else stumbled on this. My takeaway is,

enquo() returns tidyverse-specific type quosure, which has a base R type expression component + it tracks global environment for easy passing across tidy functions. It is advised to use it only within tidyverse functions.

enexpr() returns base R type expression. Since it returns a base R type, this makes it equivalent to substitute(). You can use it outside of tidyverse framework, in my case feed it into a non-tidy function inherits().

Bottomline, use enquo() within pure tidyverse functions. use enexpr() or substitute() when you need some base R interactions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment