Skip to content

Commit

Permalink
improved do_call
Browse files Browse the repository at this point in the history
  • Loading branch information
qddyy committed Nov 15, 2024
1 parent 20c4fb7 commit 24699b5
Showing 1 changed file with 19 additions and 13 deletions.
32 changes: 19 additions & 13 deletions R/do_call.R
Original file line number Diff line number Diff line change
@@ -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)))
# `formals()` returns a pairlist, which is not compatible with `as.environment()`.
args <- as.environment(as.vector(formals(func), mode = "list"))

formal_names <- names(formals)
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 `args[[name]]` here.
# https://stackoverflow.com/questions/3892580
if (!is.language(args[[name]])) {
bquote(parent.frame()$args[[.(name)]])
} else args[[name]]
}
)
)()
}

0 comments on commit 24699b5

Please sign in to comment.