Skip to content

Instantly share code, notes, and snippets.

@ianmcook
Last active April 10, 2021 03:48
Show Gist options
  • Save ianmcook/660bf3df08dc714d62aa927780c7064f to your computer and use it in GitHub Desktop.
Save ianmcook/660bf3df08dc714d62aa927780c7064f to your computer and use it in GitHub Desktop.
rlang::enquo() helpers for eager evaluation and idempotence
# enquo() helpers for eager evaluation and idempotence
# wrap eager() around enquo() to evaluate the quosure immediately in the calling
# environment *if* it can do so without error, otherwise return the quosure
eager <- function(quo) {
val <- try(eval_tidy(quo), silent = TRUE)
if (inherits(val, "try-error")) {
quo
} else {
val
}
}
# wrap idemp() around enquo() to make the the defusing operation *idempotent*;
# in other words, prevent enquo() from creating quosures inside quosures
idemp <- function(quo) {
val <- try(eval_tidy(quo), silent = TRUE)
if (is_quosure(val)) {
val
} else {
quo
}
}
# note that when you use eager(), there is no need to use idemp() with it
# because eager() also serves to make the defusing operation idempotent
# examples:
# just enquo()
a <- function(x) {
enquo(x)
}
b <- function(y) {
a(enquo(y))
}
b(z)
## <quosure>
## expr: ^enquo(y)
## env: 0x7f899bb14478
z <- 1
b(z)
## <quosure>
## expr: ^enquo(y)
## env: 0x7f899bb14478
rm(z)
# eager(enquo())
a <- function(x) {
eager(enquo(x))
}
b <- function(y) {
a(eager(enquo(y)))
}
b(z)
## <quosure>
## expr: ^z
## env: global
z <- 1
b(z)
## [1] 1
rm(z)
# idemp(enquo())
a <- function(x) {
idemp(enquo(x))
}
b <- function(y) {
a(idemp(enquo(y)))
}
b(z)
## <quosure>
## expr: ^z
## env: global
z <- 1
b(z)
## <quosure>
## expr: ^z
## env: global
rm(z)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment