用于S4方法的R match.call()

时间:2015-01-13 15:57:08

标签: r

我目前正在为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

问题是:

  1. 为什么在为参数“方法”分配函数时,match.call()为此参数得到的内容是..1 insetad fo "Mclust"

  2. 为什么来自match.call()的'函数名称'是.local而不是meth1

  3. 如何从函数中的变量"Mclust"获取method

1 个答案:

答案 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做了什么。