通过列表将参数传递给函数并忽略未使用的参数

Passing arguments to a function via list and ignoring unused arguments

背景

我对使用 do.call 通过一个列表将参数传递给两个函数很感兴趣。 do.call 解决方案应忽略未使用的参数。

例子

my_sum <- function(a, b) {
    a + b
}

my_exp <- function(c, d) {
    c^d
}

args_to_use <- as.list(1:4)
names(args_to_use) <- letters[1:4]

my_wrapper <- function(fun_args = args_to_use) {
    res_one <- do.call(my_sum, fun_args)
    res_two <- do.call(my_exp, fun_args)
    res_one + res_two
}

自然地,这个例子失败了,因为多余的参数被传递给了两个函数。

想要的结果

my_wrapper_two <- function(fun_args = args_to_use) {
    res_one <- do.call(my_sum, fun_args[1:2]) # Only a, b
    res_two <- do.call(my_exp, fun_args[3:4]) # Only c, d
    res_one + res_two
}
my_wrapper_two()
# 84

寻求解决方案

我希望根据函数参数自动执行子集操作 [1:2][3:4]


备注

我正在考虑的一种方法是使用 names(formals(my_exp)) 创建所需的参数列表,如:

my_wrapper_three <- function(fun_args = args_to_use) {
    res_one <- do.call(my_sum, fun_args[names(formals(my_sum))])
    res_two <- do.call(my_exp, fun_args[names(formals(my_exp))])
    res_one + res_two
}
my_wrapper_three()

这看起来不太优雅,我想知道是否有更智能的解决方案?

更新

我想出的解决办法如下:

do_call_on_existing <- function(fun, args_list) {
    fun_args <- names(formals(fun))
    viable_args <- args_list[fun_args]
    viable_args <- Filter(Negate(is.null), viable_args)
    do.call(fun, viable_args)
}

Filter / Negate 位可防止函数失败,其中 my_sum 可能有额外的参数,导致参数列表返回 null 元素。所以代码可以工作:

my_sum <- function(a = 999, b = 999, c = 999) {a + b + c}
my_nms <- list(a = 1, b = 2) 
do_call_on_existing(my_sum, my_nms)

试试这个(... 允许您将任意数量的参数传递给 my_sum,但根据您的定义只使用 ab):

my_sum <- function(a, b, ...) {
    a + b
}

my_exp <- function(c, d, ...) {
    c^d
}

args_to_use <- as.list(1:4)
names(args_to_use) <- letters[1:4]

my_wrapper <- function(fun_args = args_to_use) {
    res_one <- do.call(my_sum, fun_args)
    res_two <- do.call(my_exp, fun_args)
    res_one + res_two
}