diff --git a/R/do_call.R b/R/do_call.R index 477d1fb..6cc5956 100644 --- a/R/do_call.R +++ b/R/do_call.R @@ -1,19 +1,25 @@ # Updates the formals of a function with specified arguments before calling it. # Enables non-standard evaluation by allowing expressions in certain arguments. -# Example: `do_call(func, list(args = bquote(.(constant_here) + symbol_here)))` do_call <- function(func, default = list(), fixed = list(), ...) { - # use `as.list()` because `formals()` returns a pairlist - formals <- as.environment(as.list(formals(func))) + # Use `as.list()` because `formals()` returns a pairlist. + args <- as.environment(as.list(formals(func))) - formal_names <- names(formals) + # Use `base::list2env()` over `utils::modifyList()` for minimal dependency. + args <- list2env(envir = args, default) + args <- list2env(envir = args, list(...)) + args <- list2env(envir = args, fixed) - # use `base::list2env()` over `utils::modifyList()` for minimal dependency - formals <- list2env(envir = formals, default) - formals <- list2env(envir = formals, list(...)) - formals <- list2env(envir = formals, fixed) - - formals <- as.list.environment(formals, all.names = TRUE)[formal_names] - - # `func` should be non-primitive - `formals<-`(func, value = formals)() + # `func` should be non-primitive. + `formals<-`( + func, value = lapply( + `names<-`(names(args), names(args)), + function(name) { + # `args[[name]]` might be a "missing symbol object". Always use the full form here. + # https://stackoverflow.com/questions/3892580 + if (!is.language(args[[name]])) { + bquote(parent.frame()$args[[.(name)]]) + } else args[[name]] + } + ) + )() } \ No newline at end of file