another question中,在函数内部使用sapply(substitute(...()), as.character)来获取传递给该函数的名称。 as.character部分听起来不错,但是...()在做什么?

这不是substitute之外的有效代码:

> test <- function(...) ...()
> test(T,F)
Error in test(T, F) : could not find function "..."

其他一些测试用例:
> test <- function(...) substitute(...())
> test(T,F)
[[1]]
T

[[2]]
F

> test <- function(...) substitute(...)
> test(T,F)
T

最佳答案

这是...()为何按其方式工作的示意图。稍后,我将提供更多详细信息和引用,但这涉及到关键点。

  • 在对其任何组件执行替换之前,substitute()首先解析R语句。
  • ...()解析为调用对象,而...解析为名称对象。
  • ...是一个特殊对象,仅在函数调用中使用。结果,实现替换的C代码在调用对象中找到...时会采取特殊措施来处理它。当...作为符号出现时,不会采取类似的预防措施。 (相关代码位于do_substitute中的函数substitutesubstituteListR_SRCDIR/src/main/coerce.c(尤其是后两个)中。)

  • 因此,()...()中的作用是使该语句被解析为调用(aka语言)对象,以便替换将返回点的完全展开的值。即使...位于()的外部,它似乎也被替换了,但这似乎令人惊讶,但是:(a)调用在内部存储为类列表对象,并且(b)相关的C代码似乎在第一个元素之间没有区别该列表以及后续列表中的一个。

    附带说明:对于检查substitute或各种对象的类的行为,我发现设置一个小沙箱很有用,如下所示:
    f <- function(...) browser()
    f(a = 4, 77, B = "char")
    ## Then play around within the browser
    class(quote(...))  ## quote() parses without substituting
    class(quote(...()))
    substitute({...})
    substitute(...(..., X, ...))
    substitute(2 <- (makes * list(no - sense))(...))
    

    10-08 19:57