Reputation: 341
I have a function that I want to pass a function to. However, I can't seem to get it to work using the tidy_eval context.
Here is some data:
df <- tribble(
~A, ~B,
"hi", "hello",
"bye", "later"
)
I want to be able to call the function like so:
my_quoting_fn(df, A, str_detect(., pattern = "h*"))
where the third parameter can be any different function.
Here is my first attempt to write the function:
my_quoting_fn <- function(df, col, func) {
func <- enquo(func)
expr <- quo_get_expr(func)
df %>%
pull({{col}}) %>%
eval(expr)
The above gives the error:
Error in eval(., expr) : invalid 'envir' argument of type 'language'`
If I try:
my_quoting_fn <- function(df, col, func) {
df %>%
pull({{col}}) %>%
{{func}}
I get the error
Error in stri_detect_regex(string, pattern, negate = negate, opts_regex = opts(pattern)) : object '.' not found
Upvotes: 3
Views: 276
Reputation: 43334
If you don't want to tilde-quote, you'll need to quote the expression and parse it into a form rlang::as_function
understands before converting it so it can be called:
library(tidyverse)
df <- tribble(
~A, ~B,
"hi", "hello",
"bye", "later"
)
my_quoting_fn <- function(df, col, func) {
func <- enexpr(func) %>% # only want the expression, not the environment of a quosure
rlang::new_formula(NULL, .) %>% # tilde-quote the expression
rlang::as_function() # make it a formula
df %>%
pull({{col}}) %>%
func()
}
my_quoting_fn(df, A, str_detect(., pattern = "h*"))
#> [1] TRUE TRUE
This isn't a well-known idiom, though; keeping it simple is probably better.
Upvotes: 1
Reputation: 36076
If you pass your function as a formula with a tilde (~
) you could use rlang::as_function()
.
my_quoting_fn <- function(df, col, func) {
func = as_function(func)
df %>%
pull({{col}}) %>%
func
}
my_quoting_fn(df, A, ~str_detect(., pattern = "h*"))
[1] TRUE TRUE
Upvotes: 4