當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


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。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。