将对象列为具有可覆盖列表元素默认值的函数参数

时间:2018-10-07 22:55:01

标签: r list arguments metaprogramming

我有一个R函数,该函数带有大量我想作为列表传递的参数(18)。可以这么说,当我手动运行此功能时,我通常希望使用所有默认值,但要使用一两个默认值,但是我也想使用默认和非默认项的各种组合来多次运行此功能。希望以编程方式组装为列表。

我知道我可以将18个以上的参数作为单个形式,然后将它们组合到函数内部的列表中,但是我希望我可以将列表作为形式的默认值,然后让元素具有默认值也一样像这样:

> f <<- function(x, y = list(a=0, b=3)) {with(y, (x + a + b))}
> f(1)
[1] 4
> f(x=1, y$a = 1)
Error: unexpected '=' in "f(x=1, y$a ="

(或替代地)

In y$a <- 1 :
 Error in eval(substitute(expr), data, enclos = parent.frame()) : 
  object 'a' not found 

,但输出为5而不是错误。我怀疑没有办法这样做,因为R无法将列表中的分配识别为创建默认值,而只能识别为创建命名元素。但是也许用形式的赋值形式?还是通过巧妙地使用do.call?

1 个答案:

答案 0 :(得分:1)

以下是一些替代方案:

1)ModifyList 。使用modifyList处理默认值。

f1 <- function(x, y = list()) {
  defaults <- list(a = 0, b = 3)
  with(modifyList(defaults, y), {
    x + a + b
  })
}

f1(x = 1)
## [1] 4
f1(x = 1, y = list(a = 1))
## [1] 5

2)do.call 。另一种可能性是具有两个功能。第一个不使用列表,第二个(用户调用的列表)使用do.call来调用第一个。

f2impl <- function(x, a = 0, b = 3) x + a + b
f2 <- function(x, y = list()) do.call("f2impl", c(x, y))

f2(x = 1)
## [1] 4
f2(x = 1, y = list(a = 1))
## [1] 5