2012-09-22 5 views
7

Ich schreibe gerade ein Paket mit Referenzklassen. Ich habe über ein Problem kommen, die aus der Lektüre verschiedene Quellen:Referenzklassen, Registervervollständigung und erzwungene Methodendefinition

Method initialisation in R reference classes

Can't reliably use RefClass methods in Snowfall

entnehme ich, wird dadurch verursacht, dass die Referenzmethoden nicht alle zu jedem kopiert sind in der Klasse Objekt eher sind sie kopiert beim ersten Zugriff.

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

Als Beispiel definieren:

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

example <- test$new() 

So Beispiel ist ein neues Objekt der Klasse TEST. Typing example$ und Tabbing in der Konsole gibt

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

so dass die Methode addone wird nicht als Option dargestellt. Es ist jedoch zu Aufruf zur Verfügung:

example$addone() 

nun wieder Tabbing enthüllt

# > 
# > 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 

so jetzt addone und field und show werden als Optionen dargestellt.

Martin Morgan empfiehlt, die Definition der Methoden in einem der obigen Links zu erzwingen. Diese funktioniert gut

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() 

so jetzt tabbing gibt:

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

Einige meiner Klassen haben über 30 Methoden so würde Ich mag diese möglichst kurz und bündig tun. Ich habe definiert:

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() 

Tabbing gibt jetzt:

# > 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  

Während dies funktioniert es ein wenig unbeholfen fühlt. Auch [email protected] wird eher verwendet als getRefClass("TEST")[email protected], so dass fühlt sich ein bisschen falsch an. Hat jemand schon einmal mit diesem Problem zu tun gehabt?

Gibt es eine bessere Lösung für eine Lösung? Vielen Dank für jegliche Beratung und Entschuldigung, wenn die Frage übertrieben ist.

Antwort

6

Ich frage mich, was Ihr Ziel ist? Funktionsnamen werden mit der Tab-Vervollständigung angezeigt? Dann lohnt sich ein Post in der R-devel-Mailingliste mit einer Feature-Anfrage. Das ursprüngliche Szenario wird eleganter gehandhabt mit usingMethods wie auf ?setRefClass dokumentiert.Eine Fortsetzung Hack könnte

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

Tab Fertigstellungen sein können über .DollarNames im utils Paket angepasst werden, so

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

Vielleicht hierfür eine S3-Methode an der Basis Ihrer Klassenhierarchie geschrieben werden könnte?

+0

Vielen Dank, dass ist sehr hilfreich und eleganter als meine Lösung. Ich wusste auch nicht, dass es Tab-Completion genannt wurde. Mit diesem Begriff konnte ich das relevante Paket in den Utils finden. Tab-Vervollständigung mit Referenzklassen war mein Ziel und ich werde den Fragetitel bearbeiten, um dies besser widerzuspiegeln. – jdharrison

+0

Das scheint sehr vielversprechend. Wäre es eine schlechte Idee, '.DollarNames.envRefClass <- function (x, pattern) grep (Muster, getRefClass (class (x)) $ methods(), value = TRUE)' zu meinem Paket hinzuzufügen? – jdharrison

+0

Ja, es wäre eine schlechte Idee - Sie würden das Verhalten für alle Referenzklassen ändern, nicht nur für Ihre eigenen. Vielleicht mögen manche ihr aktuelles Verhalten, vielleicht werden 'Methoden' zu irgendeinem späteren Zeitpunkt eine super-duper' .DollarNames.envRefClass' implementieren und Ihre lang vergessene Methode wird dies dann überschreiben. R-devel sollte als Feature-Request eingeführt werden, insbesondere, wenn Sie zumindest einen funktionierenden Prototyp haben, um das Verhalten zu veranschaulichen, das Sie für angemessen halten. –

1

@Martin Morgan bemerkte, dass dies als Tab Completion bezeichnet wurde. Das Paket rcompletion und später rcompgen wurde damit beauftragt. Sie wurden jetzt zu utils verschoben.

rcompletion update

ich durch den Code gesucht completion.R und von dem, was ich feststellen konnte utils:::.DollarNames.environment Referenz Klassen Tabulatorvervollständigung wurde Handling.

completion.R

die Funktion neu definieren schien Tabulatorvervollständigung zu erreichen:

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") 

Einige Dinge zu beachten:

  • ich nur für meine eigenen Gebrauch verwenden würde. Momentan debugge und dokumentiere ich ein Paket. Ich hatte einige langwierige Methodennamen und konnte mich nicht genau daran erinnern, was sie waren, so dass die Tab-Vervollständigung sehr hilfreich sein wird.

  • Die Verwendung von assignInNamespace in einem Paket ist verpönt (wenn nicht verboten) siehe ?assignInNamespace.

  • Gezwungene Definition von Methoden ist ratsam.

+0

Eigentlich ist '.DollarNames' ein generischer S3, so dass Sie S3-Methoden darauf schreiben können; Ich habe das in meiner Antwort illustriert. –

3

Ich weiß, dass dies eine alte Frage, aber es ist immer noch der oberste Eintrag, wenn für refClass Tabulatorvervollständigung auf Google suchen, so dass ich nur ein Update hinzufügen:

Statt grep in der zu verwenden. DollarNames Funktion wie von Martin vorgeschlagen, die Verwendung findMatches vom utils-Paket, wie es spielt besser mit den verschiedenen Rgui der um (grep Ihre teilweise eingegebene Name beim Auftreffen auf Registerkarte löschen)

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

Dies ist auch, wie Tabulatorvervollständigung intern gehandhabt wird für Listen und Daten.frames

Verwandte Themen