R中S4方法的match.call()函数

3

我目前正在为一个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. 为什么将一个函数分配给参数'method'时,从match.call()获取到该参数的内容是..1而不是"Mclust"

  2. 为什么从match.call()获取的'函数名'是.local而不是meth1

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


你能澄清一下第三个问题的意思吗?你是想将 MClust 符号解释为字符吗?换句话说,你想让用户在输入 MClust 时无需加引号吗? - BrodieG
事实上,您已经回答了所有的问题。我想要的是将字符串“MClust”分配给method - carlesh
1个回答

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

因此,回答问题2,你得到.local的原因是因为有一系列的调用最终导致了你所定义的函数的评估,并且S4将该函数存储为.local
问题1的答案很复杂,但你可以在我的软件包中附带的vignette中查看详细信息。请注意,在C代码内部,...参数具有名称..1..2等(来自R Internals):
回想一下,函数的评估框架最初包含匹配调用的名称=值对,因此对于...也是如此。...的值是一个(特殊的)pairlist,其元素由特殊符号..1、..2等引用,这些符号具有DDVAL位:当遇到其中之一时,它会在评估框架中...符号的值中查找(通过ddfindVar)。
关于问题3,我不明白。您是否希望能够将未引用的变量作为参数“method”输入,然后将其解释为字符?
请注意,该软件包目前仅在github上,但您可以使用sys.calls来满足您的需求。例如,如果我们在您的方法内运行print(sys.calls()),我们会得到:
[[1]]
meth1(new("AClass"), method = Mclust)

[[2]]
meth1(new("AClass"), method = Mclust)

[[3]]
.local(object, ...)

您可以直接使用该方法,但前提是在调用时完全指定参数名称(即如果某人执行meth1(x,"blah"),则您将无法在sys.calls中获得method = 部分。 如果您有多个参数或部分指定的参数(例如meth = X),则需要更多工作来匹配内容(这正是match_call所做的)。请注意保留HTML标签和原格式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接