2012-09-22 40 views
7

我目前正在使用參考類編寫一個包。我所遇到 一個問題,從閱讀各種來源:參考類,選項卡完成和強制方法定義

Method initialisation in R reference classes

Can't reliably use RefClass methods in Snowfall

我收集的造成的,因爲參考方法是不是所有複製到每個類中的對象 相反,它們是第一次訪問時複製。

https://stat.ethz.ch/pipermail/r-devel/2011-June/061261.html

作爲示例定義:

test <- setRefClass("TEST", 
       fields = list(a = "numeric"), 
       methods = list(
        addone = function(){ 
             a <<- a+1 
             }, 
        initialize = function(){ 
              a <<- 1 
              } 
          ) 
       ) 

example <- test$new() 

所以例如是TEST類的新對象。鍵入example$並在 控制檯的互聯提供了

> example$ 
# example$.->a   example$.refClassDef example$.self   
# example$a   example$initialize 

所以這種方法addone沒有提出作爲一個選項。它是提供給然而 電話:

example$addone() 

現在的互聯又透着

# > 
# > example 
# Reference class object of class "TEST" 
# Field "a": 
# [1] 2 
# > example$ 
# example$.->a   example$.refClassDef example$.self   
# example$a   example$addone  example$field   
# example$initialize example$show 

所以現在addonefieldshow都作爲選項。

Martin Morgan建議在上述鏈接之一中強制定義方法。這 作品以及

test <- setRefClass("TEST", 
       fields = list(a = "numeric"), 
       methods = list(
        addone = function(){ 
             a <<- a+1 
             }, 
        initialize = function(){ 
              a <<- 1 
              .self$addone #force definition 
              } 
          ) 
       ) 

example <- test$new() 

所以現在黏合給出:

# > example$ 
# example$.->a   example$.refClassDef example$.self   
# example$a   example$addone  example$initialize 

我的一些類的有30的方法,所以我想這樣做,因爲succintly越好。 我已經定義:

test <- setRefClass("TEST", 
       fields = list(a = "numeric"), 
       methods = list(
        addone = function(){ 
             a <<- a+1 
             }, 
        initialize = function(){ 
         a <<- 1 
         eval(parse(text=paste0('.self$',ls([email protected])))) 
              } 
          ) 
       ) 

example <- test$new() 

的互聯現在給:

# > example$ 
# example$.->a   example$.refClassDef example$.self   
# example$a   example$addone  example$callSuper  
# example$copy   example$export  example$field   
# example$getClass  example$getRefClass example$import  
# example$initFields example$initialize example$show   
# example$trace  example$untrace  

雖然這工作感覺有點笨拙。此外使用[email protected]而不是getRefClass("TEST")[email protected],因此 感覺有點不對。有沒有人以前處理過這個問題。

有沒有更好的方法來解決問題?感謝您提出任何建議和道歉,如果這個問題太過分了。

回答

6

我想知道你的目標是什麼?功能名稱與選項卡完成一起顯示?然後,這是一個值得R-devel郵件列表發佈功能請求的帖子。原始場景更加優雅地處理,usingMethods?setRefClass所述。持續的黑客可能是

initialize = function(...) { 
    methods <- getRefClass(class(.self))$methods() 
    eval(parse(text=paste0(".self$", methods))) 
    callSuper(...) 
} 

標籤的完成可以通過.DollarNamesutils包進行定製,所以

.DollarNames.TEST <- function(x, pattern) 
    grep(pattern, getRefClass(class(x))$methods(), value=TRUE) 

可能的S3方法可以在你的類層次結構的這個基地寫?

+0

謝謝你,這是非常有幫助的,比我的解決方案更優雅。我也不知道它被稱爲製表符完成。知道這個術語使我能夠在utils中找到相關的軟件包。使用引用類完成Tab完成是我的目標,我將編輯問題標題以更好地反映此問題。 – jdharrison

+0

這看起來很有希望。將'.DollarNames.envRefClass < - function(x,pattern)grep(pattern,getRefClass(class(x))$ methods(),value = TRUE)'添加到我的包中是不是一個好主意? – jdharrison

+0

是的,這將是一個壞主意 - 你會改變所有參考類的行爲,而不僅僅是你自己的行爲。也許有些人喜歡它是當前的行爲,也許''方法'將在未來某個時候實現一個超級傻瓜'.DollarNames.envRefClass',然後你長久以來被遺忘的方法將覆蓋這個。要做的正確的事情就是將它作爲功能請求提交給R-devel,特別是現在至少有一個工作原型可以說明您認爲合適的行爲。 –

1

@馬丁摩根指出,這一被命名選項卡完成。該軟件包rcompletion後來rcompgen與實現這一任務了。他們現在已被轉移到utils

rcompletion update

我看着直通代碼爲completion.R從我可以決定utils:::.DollarNames.environment正在處理選項卡完成對引用類。

completion.R

重新定義的功能似乎實現tab完成:

assignInNamespace(x = ".DollarNames.environment", 
        function(x, pattern = "") { 
    y <- NULL 
    if(isS4(x) && !is.null(x[['.refClassDef']])){ 
     if(.hasSlot(x$.refClassDef,'refMethods')){ 
     y<[email protected] 
     y<-ls(y, all.names = TRUE, pattern = pattern) 
     } 
    } 
    x<-ls(x, all.names = TRUE, pattern = pattern) 
    unique(c(x,y)) 
               } 
,ns = "utils") 

需要注意以下幾點:

  • 我只會用這個爲我所用。目前我正在調試和記錄一個包。我有一些很長的方法名稱,並不能確切地記住它們是什麼,所以選項卡完成將會有很大幫助。

  • 在包裝中使用assignInNamespace(如果不禁止)請參閱?assignInNamespace

  • 強制的方法定義是更明智。

+0

其實''.DollarNames'是S3通用的,所以你可以在其上編寫S3方法;我在我的回答中說明了這一點。 –

3

我知道這是一個老問題,但仍對谷歌refClass標籤完成搜索時它是頂面入口,所以我就補充更新:

而不是在用grep的。馬丁DollarNames功能的建議,從utils軟件包使用findMatches,因爲它起着與不同RGUI的周圍更好(grep的將刪除在打標籤的部分輸入的名稱)

.DollarNames.TEST <- function(x, pattern){ 
    utils:::findMatches(pattern, getRefClass(class(x))$methods()) 
} 

這也是如何選項卡完成在內部處理列表和數據框架