我目前正在为S4类编写一个方法,我希望调用该方法,就好像它是一个函数并使用match.call()。
这是我正在做的最简单的例子:
setClass(
Class = "AClass",
representation = representation(
name = "character"
)
)
setGeneric("meth1", function(object, ...) {
standardGeneric("meth1")
})
setMethod(
f = "meth1",
signature = "AClass",
definition = function(object, method, ..., warnings = TRUE) {
# ...
print(match.call())
return(NA)
})
根据这个定义,我看到:
> meth1(new("AClass"), method = "MClust")
.local(object = object, method = "MClust")
[1] NA
> meth1(new("AClass"), method = Mclust)
.local(object = object, method = ..1)
[1] NA
问题是:
为什么在为参数“方法”分配函数时,match.call()
为此参数得到的内容是..1
insetad fo "Mclust"
?
为什么来自match.call()
的'函数名称'是.local
而不是meth1
?
如何从函数中的变量"Mclust"
获取method
?
答案 0 :(得分:2)
当match.call
涉及...
和多层函数调用时,match.call
的工作原理存在一些问题。这与...
搜索词法堆栈以找到要替换的devtools::install_github("brodieg/matchcall") # <-- the package in question
library(matchcall)
setMethod(
f = "meth1",
signature = "AClass",
definition = function(object, method, ..., warnings = TRUE) {
# ...
print(match.call())
print(match_call())
print(match_call(2))
return(NA)
})
meth1(new("AClass"), method = Mclust)
而不是动态堆栈有关。我写了一个包来试图纠正这些问题:
.local(object = object, method = ..1) # match.call
.local(object = object, method = Mclust) # match_call(), my package
meth1(object = new("AClass"), method = Mclust) # match_call(2), my package offset
[1] NA
产地:
.local
因此,回答问题2,你得到.local
的原因是因为有一系列调用最终会导致对你定义的函数的评估,并且S4将该函数存储为{{1 }}
问题1的答案很复杂,但您可以查看我的软件包附带的 vignette 中的详细信息。请注意,C代码...
内部的参数名称为..1
,..2
等(来自R Internals):
回想一下,函数的求值框最初包含匹配调用中的name = value对,因此对于...也是如此。 ......的值是一个(特殊的)pairlist,其元素由特殊符号..1,..2,...引用,它们设置了DDVAL位:当遇到其中一个时,它被查找(通过ddfindVar) )在评估框架中的...符号的值。
问题3,我不明白。您是否希望能够将未加引号的变量作为参数&#34;方法&#34;,然后将其解释为字符?
请注意,该软件包目前仅在github上,但您可以使用sys.calls
来满足您的需求。例如,如果我们在您的方法中运行print(sys.calls())
,我们会得到:
[[1]]
meth1(new("AClass"), method = Mclust)
[[2]]
meth1(new("AClass"), method = Mclust)
[[3]]
.local(object, ...)
您可以直接使用它,但只有在调用中完全指定参数名称时才能正常工作(即如果有人meth1(x, "blah")
,您就不会获得method=
sys.calls
中的部分内容。如果您有多个参数或部分指定的参数(例如meth=X
),那么您将需要做更多的工作来匹配内容(而这正是如此) match_call
做了什么。