I want to create a function check_sym
that takes another function f
as argument and checks whether inside f
a specific function is used.
Specifically I want to check if inside f
non-standard evaluation in the form of !! sym
is used.
I can do this with a simple trick that turns a functions body into a character string and then uses regex to check for "!!sym\\("
.
library(dplyr)
library(purrr)
library(rlang)
check_sym <- function(f) {
f <- as.list(body(f))
f <- unlist(as.character(f))
purrr::some(f, function(x) grepl("!!sym\\(", x))
}
foo <- function(df, x) {
select(df, !! sym(x))
}
check_sym(foo)
#> [1] TRUE
Created on 2020-02-16 by the reprex package (v0.3.0)
However, while this is possible, I am looking for a way that does not rely on character strings and regex, but rather ideally some method which looks inside the function and "sees" all function calls at a deeper level, which would be more reliable.
Any ideas appreciated.
Final solution based on accepted answer:
Based on MrFlick's answer below my actual solution is the following:
I define check_syms as:
check_sym <- function(f) {
grepl("!!sym", paste(all.names(body(f)), collapse = ""))
}
It correctly identifies functions which make a function call to "!! sym"
compared to functions that only call for example paste0("!!sym")
.
foo <- function(df, x) {
select(df, !! sym(x))
}
test_f <- function(x) {
print(paste0("!!sym", x))
}
check_sym(foo)
#> [1] TRUE
check_sym(test_f)
#> [1] FALSE
In base R
, we can capture the output of body
into a vector of strings and use grepl
check_sym <- function(f) any(grepl('!!sym(', capture.output(body(f)), fixed = TRUE))
check_sym(foo)
# [1] TRUE
some_fct <- function(x) print("sym")
check_sym(some_fct)
#[1] FALSE
You could use the all.names
function. It pulls out the names of all the variables/function defined inside the function
all.names(body(foo))
# [1] "{" "select" "df" "!" "!" "sym"
# [7] "x"
Part of the problem with your specific example is that !!sym
isn't really a simple variable. It's more like a call to !(!(sym))
to the parser. The !!
stuff really isn't a special operator to the R parser, it's just two calls to the negation operator which rlang re-interprets via non-standard evaluation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With