do.call()在没有默认值的情况下存在的行为

时间:2013-08-07 16:13:46

标签: r arguments do.call

这个问题是对previous answer提出疑问的后续行动。

上一个答案的可重复示例:

Models <- list( lm(runif(10)~rnorm(10)),lm(runif(10)~rnorm(10)),lm(runif(10)~rnorm(10)) )
lm1 <- lm(runif(10)~rnorm(10))
library(functional)
# This works
do.call( Curry(anova, object=lm1), Models )
# But so does this
do.call( anova, Models )

问题是为什么do.call(anova, Models)正常工作,正如@Roland指出的那样?

anova的签名是anova(object, ...)

anova来电UseMethod,应致电anova.lm,呼叫anova.lmlist,其第一行为objects <- list(object, ...),但object不会不存在于那种表述中。

我唯一可以猜测的是do.call可能不只是填充省略号而是填充所有参数而没有默认值,并留下任何额外的省略号来捕获?如果是这样,记录在哪里,因为它对我来说绝对是新的!

*这本身就是一个线索 - 如果第一个参数未指定,UseMethod如何知道调用anova.lm?没有anova.list方法或anova.default或类似方法......

3 个答案:

答案 0 :(得分:4)

在常规函数中,...通过位置,部分匹配和完全匹配来捕获参数:

f <- function(...) g(...)
g <- function(x, y, zabc) c(x = x, y = y, zabc = zabc)

f(1, 2, 3)
# x    y zabc 
# 1    2    3     
f(z = 3, y = 2, 1)
# x    y zabc 
# 1    2    3     

do.call的行为方式完全相同,除了不直接向函数提供参数,它们存储在列表中,do.call负责将它们传递给函数:

do.call(f, list(1, 2, 3))
# x    y zabc 
# 1    2    3     
do.call(f, list(z = 3, y = 2, 1))
# x    y zabc 
# 1    2    3     

答案 1 :(得分:2)

我认为值得强调的是列表元素的名称很重要。哈德利提到了它,但这可能是一个烦恼。考虑下一个例子:

x <- rnorm(1000)
y <- rnorm(1000)
z <- rnorm(1000) + 0.2

Models <- list()
Models$xy <- lm(z~x)
Models$yz <- lm(z~y)

# This will fail, because do.call will not assign anything to the argument "object" of anova
do.call(anova, Models)
# This won't
do.call(anova, unname(Models))

答案 2 :(得分:1)

do.call将列表的第一个元素传递给第一个参数:

fun <- function(x,...) {
  print(paste0("x=",x))

  list(x, ...)
}

do.call(fun, list(1,2))
# [1] "x=1"
# [[1]]
# [1] 1
# 
# [[2]]
# [1] 2