5

这个问题是对之前提出的一个谜题的回答的后续问题。

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

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(object, ...)

anovacall UseMethod,应该* callanova.lm应该 call anova.lmlist,其第一行是objects <- list(object, ...),但object在该公式中不存在。

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

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

4

3 回答 3

5

在常规函数调用...中按位置、部分匹配和完全匹配捕获参数:

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     
于 2013-08-08T17:15:16.463 回答
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))
于 2013-11-08T23:25:02.650 回答
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
于 2013-08-07T16:42:49.750 回答