I'm trying to parse user input as arguments to a function call (within an expression). It seems like I'm close but !!! is wrapping my arguments in parenthesis which is not working. I'm trying to recreate the following with user inputs:
recipe(mpg ~ cyl + hp + wt + disp, data = mtcars) %>%
step_log(disp, base = 10, offset = 0) %>%
prep()
library(rlang)
library(tidymodels)
user_dv <- "mpg"
user_idv <- c("cyl", "hp", "wt", "disp")
user_step <- "log"
user_selector <- "disp"
user_args <- "base = 10, offset = 0"
formula <- as.formula(paste(user_dv, paste(user_idv, collapse = " + "), sep = " ~ "))
rcp <- expr(recipe(!!formula,data = mtcars))
add_step <- function(x, step, selector, args){
f <- parse_expr(paste0("step_", step))
vars <- ensym(user_selector)
args <- args %>%
str_replace(",", ";") %>%
parse_exprs()
step_expr <- call2(f, vars, !!!args)
expr(!!x %>% !!step_expr)
}
rcp %>%
add_step(user_step, user_selector, user_args) %>%
eval() %>%
prep()
My expression ends up looking like this:
recipe(mpg ~ cyl + hp + wt + disp, data = mtcars) %>%
step_log(disp, (base = 10), (offset = 0))
Which does not prep()
After
parse_exprs()
, you end up with assignment expressions stored in an unnamed list:while, to get the effect you want with
!!!
, they need to be values in a named list:With that said, I suggest "forwarding the dots" instead, because it leads to a simpler and more flexible implementation:
The user can now simply provide the desired arguments directly to
add_step()
:OR store them in a list and use
!!!
on your function: