当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


R dotsMethods 在方法签名中使用...


R语言 dotsMethods 位于 methods 包(package)。

说明

“...” 参数R函数被特殊对待,因为它匹配零个、一个或多个实际参数(以及对象)。添加了一个机制R允许 “...” 作为通用函数的签名。为此类函数定义的方法将在以下情况下被选择和调用:全部匹配 “...” 的参数来自指定的类或该类的某个子类。

在签名中使用"..."

从 2.8.0 版本开始R,可以根据特殊参数“...”调度(选择和调用)S4方法。目前,“...” 不能与其他形式参数混合:泛型函数的签名或者仅为“...”,或者不包含“...”。 (此限制可能会在未来版本中取消。)

给定一个合适的通用函数,可以通过调用 setMethod 以通常的方式指定方法。编写方法定义时,必须期望与 “...” 对应的所有参数都来自方法签名中指定的类,或者来自扩展该类的类(即该类的子类)。

通常,这些方法会将 “...” 传递给另一个函数,或者创建一个参数列表并对其进行迭代。请参阅下面的示例。

当您的计算适合多个现有类时,一种方便的方法可能是通过调用 setClassUnion 来定义这些类的并集。请参阅下面的示例。

"..."的方法选择和调度

有关一般讨论,请参阅Methods_Details。以下假设您已阅读该文档的“方法选择和调度”部分。

“...” 上选择的方法由调用 setMethod 中的单个类指定。如果“...”对应的所有实参都有这个类,则直接选择对应的方法。

否则,从第一个 “...” 参数开始计算每个参数的类以及该类的超类。对于第一个参数,合格的方法是适用于任何类的方法。对于引入先前未考虑的类的每个后续参数,合格的方法进一步限制为与参数的类或超类匹配的方法。如果不存在其他符合条件的类,则迭代将中断并选择默认方法(如果有)。

在迭代结束时,一种或多种方法可能是合格的。如果超过一个,则选择查找与实际参数距离最小的方法。对于每个参数,任何继承的方法都对应于一个距离,可从类定义的 contains 槽中获取。由于同一类可以出现多个参数,因此可能有多个与之相关的距离。将它们组合起来不可避免地是任意的:当前的计算使用最小距离。因此,例如,如果一个方法直接匹配一个参数,一个作为第一代超类,另一个作为第二代超类,则距离为 0、1 和 2。当前选择计算将对此方法使用距离 0。特别是,此选择标准倾向于使用与一个或多个参数类别完全匹配的方法。

与普通的方法选择一样,可能存在多个具有相同距离的方法。发出警告消息并选择其中一种方法(第一个遇到的方法,在本例中是相当任意的)。

请注意,虽然计算检查所有参数,但分派的基本成本随着参数中不同类的数量而增加,当后者很大时,可能比参数数量小得多。

实施细节

在 “...” 上调度的方法是在 2.8.0 版本中引入的R。相应的选择和调度的初始实现是在 R 函数中实现的,以便在研究新机制时保持灵活性。在此实现中,本地版本standardGeneric被插入到通用函数的环境中。本地版本根据上述标准选择一个方法,并从通用函数的环境中调用该方法。这与不涉及 “...” 时 C 实现所采取的操作略有不同。除了需要额外的计算时间之外,该方法是在真正的函数调用中计算的,而不是由 C 版本构建的特殊上下文(无法在 R 代码中完全复制)。但是,在不同的计算结果的情况下到目前为止还没有遇到过,而且看起来可能性很小。

通过将继承的方法存储在所有方法的表中来缓存除 “...” 以外的参数上分派的方法,在下一个选择中可以在实际参数中使用相同的类组合找到该方法(但不用于继承搜索) 。基于“...”的方法也被缓存,但没有立即找到。如前所述,所选方法仅取决于 “...” 参数中出现的类集。这些类中的每一个都可以出现一次或多次,因此实际参数类的许多组合将产生相同的有效签名。选择计算首先计算并排序遇到的不同类。这给出了一个标签,该标签将缓存在所有方法的表中,从而避免在第一次出现后进一步搜索继承的类。对showMethods 的调用将公开此类继承的方法。

目的是当获得足够的经验后,“...” 函数将被添加到标准 C 代码中。同时,可能支持 “...” 与签名中其他参数的组合。

例子

cc <- function(...)c(...)

setGeneric("cc")

setMethod("cc", "character", function(...)paste(...))

setClassUnion("Number", c("numeric", "complex"))

setMethod("cc", "Number", function(...) sum(...))

setClass("cdate", contains = "character", slots = c(date = "Date"))

setClass("vdate", contains = "vector", slots = c(date = "Date"))

cd1 <- new("cdate", "abcdef", date = Sys.Date())

cd2 <- new("vdate", "abcdef", date = Sys.Date())

stopifnot(identical(cc(letters, character(), cd1),
           paste(letters, character(), cd1))) # the "character" method

stopifnot(identical(cc(letters, character(), cd2),
                    c(letters, character(), cd2)))
# the default, because "vdate" doesn't extend "character"

stopifnot(identical(cc(1:10, 1+1i), sum(1:10, 1+1i))) # the "Number" method

stopifnot(identical(cc(1:10, 1+1i, TRUE), c(1:10, 1+1i, TRUE))) # the default

stopifnot(identical(cc(), c())) # no arguments implies the default method

setGeneric("numMax", function(...)standardGeneric("numMax"))

setMethod("numMax", "numeric", function(...)max(...))
# won't work for complex data
setMethod("numMax", "Number", function(...) paste(...))
# should not be selected w/o complex args

stopifnot(identical(numMax(1:10, pi, 1+1i), paste(1:10, pi, 1+1i)))
stopifnot(identical(numMax(1:10, pi, 1), max(1:10, pi, 1)))

try(numMax(1:10, pi, TRUE)) # should be an error:  no default method

## A generic version of paste(), dispatching on the "..." argument:
setGeneric("paste", signature = "...")

setMethod("paste", "Number", function(..., sep, collapse) c(...))

stopifnot(identical(paste(1:10, pi, 1), c(1:10, pi, 1)))


参考

Chambers, John M. (2008) Software for Data Analysis: Programming with R Springer. (For the R version.)

Chambers, John M. (1998) Programming with Data Springer (For the original S4 version.)

也可以看看

有关方法的一般讨论,请参阅Methods_Details 和其中的链接。

相关用法


注:本文由纯净天空筛选整理自R-devel大神的英文原创作品 The Use of ... in Method Signatures。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。