正如@joran 已经指出的那样,formals() 公开了默认值。但是,据我了解,您真正追求的是 调用表达式 的构造。为此,将formals() 与as.call() 组合起来生成调用本身是很有用的。以下函数通过为给定的函数名称f 生成一个产生“参数完成调用”的函数来做到这一点:
drop_missing <- function(sig) {
sig[!sapply(sig, identical, quote(expr =))]
}
complete_call <- function(f) {
nm <- as.name(f)
sig <- formals(args(f))
make_call <- function() {
args <- match.call()[-1]
sig[names(args)] <- args
as.call(c(nm, drop_missing(sig)))
}
formals(make_call) <- sig
make_call
}
示例用法:
complete_call("log")(1)
#> log(x = 1, base = exp(1))
complete_call("rnorm")(10)
#> rnorm(n = 10, mean = 0, sd = 1)
complete_call("rnorm")()
#> rnorm(mean = 0, sd = 1)
备注:
1) 输出是一个语言对象。要执行调用,您需要对其进行评估,例如,
eval(complete_call("rnorm")(10))
#> [1] -0.89428324 -1.78405483 -1.83972728 ... (output truncated)
2) 如果你想让complete_call() 接受一个函数,而不是函数的名字,你可以写nm <- as.name(deparse(substitute(f))) 来代替给定的赋值。但是,这在嵌套调用中是行不通的,因为 R 的词法作用域规则,你会得到 as.name("f") 对应的 nm。
3) 如果没有在 sig 的赋值中调用 args(),complete_call() 只能用于闭包,因为原始函数和内置函数没有形式。