这实在不是一件容易的事。如果你正在构建的功能,可以捕捉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
注match.call
只捕获的号召,不默认参数添加(第一个例子中没有y
)。那些可以用formals(f)
访问,因为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
据我所知,你必须保存该调用并解析它,这是一种痛苦。 – alistaire
@alistaire说,你可以使用'Sys.call()'来访问一个函数内部的调用......但是你的目标是什么? – Val