В Sat, 17 Feb 2024 11:15:43 -0700 "Reed A. Cartwright" <racartwri...@gmail.com> пишет:
> I'm wrapping a function in R and I want to record all the arguments > passed to it, including default values and missing values. This is hard if not impossible to implement for the general case because the default arguments are evaluated in the environment of the function as it is running: f0 <- function(arg = frobnicate()) { frobnicate <- switch( sample.int(3, 1), function() environment(), function(n=1) runif(n), function() alist(a=)$a ) arg } (And some arguments aren't meant to be evaluated at all.) Even starting with rlang::call_match(call = NULL, defaults = TRUE) is doomed to a certain extent because it gives you f(x = a, a = NULL) for both function(x, a = NULL), f(a) (where `a` passed as an argument `x` and `a` should be taken from the parent frame) and function(x = a, a = NULL), f() (in which case `x` defaults to `a`, which in turn defaults to NULL). I think the key here is evaluating the arguments first, then matching. This makes a lot of assumptions about the function being inspected: no NSE, no ellipsis, formals don't depend on the body, nothing weird about the environment of the function... f <- function(...) { .makemissing <- function() alist(a=)$a .ismissing <- function(x) identical(x, .makemissing()) # prepare to evaluate formals params <- formals(f0) e <- new.env(parent = environment(f0)) # assign non-missing formals for (n in names(params)) if (!.ismissing(params[[n]])) eval( # work around delayedAssign quoting its second argument call('delayedAssign', n, params[[n]], e, e) ) # match the evaluated arguments against the names of the formals args <- as.list(match.call(f0, as.call(c('f0', list(...)))))[-1] for (n in names(args)) assign(n, args[[n]], envir = e) # evaluate everything, default argument or not mget(names(params), e, ifnotfound = list(.makemissing())) } f0 <- function(x, y = 2 * z, z, a = NULL, b) NULL a <- 1 identical( f(a, z = 1 + 100), list(x = 1, y = 202, z = 101, a = NULL, b = rlang::missing_arg()) ) # [1] TRUE -- Best regards, Ivan ______________________________________________ R-help@r-project.org mailing list -- To UNSUBSCRIBE and more, see https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.