这确实不是一件容易的事。如果您正在构建该函数,您可以使用以下命令捕获调用match.call
,可以轻松解析:
f <- function(x, y = 1, ...){
cl <- match.call()
as.list(cl[-1])
}
str(f(1))
#> List of 1
#> $ x: num 1
str(f(1, 'foo'))
#> List of 2
#> $ x: num 1
#> $ y: chr "foo"
str(f(1, 'foo', list(3), fun = sum))
#> List of 4
#> $ x : num 1
#> $ y : chr "foo"
#> $ : language list(3)
#> $ fun: symbol sum
Note match.call
只捕获调用,不添加默认参数(没有y
在第一个例子中)。这些可以通过以下方式访问formals(f)
, since f
不是原始的,因此可以通过以下方式创建完整的参数
user_args <- f(1)
fun_args <- formals(f)
fun_args[names(user_args)] <- user_args
str(fun_args)
#> List of 3
#> $ x : num 1
#> $ y : num 1
#> $ ...: symbol
这种方法对于已完成的点效果不佳,但如果它们已完成,那么match.call
本身就应该足够了。要提取传递给现有函数的参数,您可以编写一个包装器match.call
,但是重建每个函数几乎不切实际,并且您捕获的调用无论如何都会看起来很有趣,除非您覆盖现有函数。只要该函数不是原始函数,您就可以使用quote
以启用formals
不过,方法是:
cl <- quote(rnorm(5, 2))
user_args <- as.list(cl[-1]) # subset call to only args
fun_args <- formals(as.character(cl[1])) # subset call to only function
names(user_args) <- names(fun_args)[seq(length(user_args))]
fun_args[names(user_args)] <- user_args
str(fun_args)
#> List of 3
#> $ n : num 5
#> $ mean: num 2
#> $ sd : num 1
另一种方法是使用 rlang,它的函数可以很好地处理原语(fn_fmls(sum)
),可以轻松可靠地提取部分调用(lang_fn
, lang_args
),准确命名未命名参数(lang_standardize
), 和更多。和purrr的新一起list_modify
(开发版本),这一切都变得相当轻松:
library(rlang)
fun_call <- quo(rnorm(5))
fun_call
#> <quosure: frame>
#> ~rnorm(5)
default_args <- fn_fmls(lang_fn(fun_call))
str(default_args)
#> Dotted pair list of 3
#> $ n : symbol
#> $ mean: num 0
#> $ sd : num 1
user_args <- lang_args(lang_standardise(fun_call))
str(user_args)
#> List of 1
#> $ n: num 5
calling_args <- purrr::list_modify(default_args, user_args)
str(calling_args)
#> Dotted pair list of 3
#> $ n : num 5
#> $ mean: num 0
#> $ sd : num 1