在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
中的函数substitute
,substituteList
和R_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))(...))