2015-12-29 14 views
8

Ich habe eine generische Funktion namens foo. Es funktioniert anders in den Klassen bar und baz, aber es gibt einige gemeinsame Vorverarbeitung, die nur einmal durchgeführt werden müssen. Was ist der idiomatische Weg, dies auszuführen?R-Muster zum Ändern von Argumenten an generische Funktion übergeben

In meinem albernen Beispiel unten möchte ich das Objekt, das an das generische übergeben wird, mit 10 multiplizieren. Doch wenn die Methode aufgerufen wird, wird der ursprüngliche Wert auf die Konsole gedruckt. Ich habe die Sprachdefinition gelesen und weiß, dass das folgende Muster nicht funktioniert. Meine Frage ist: Wo oder wie soll ich die gemeinsame Verarbeitung von generischen Argumenten behandeln, bevor ich die Methode aufruft?

a <- structure(1:5, class="bar") 
b <- structure(6:10, class="baz") 

foo <- function(x) { 
    x <- x * 10 # where should shared preprocessing go? 
    UseMethod("foo") 
} 

foo.bar <- function(x) { 
    cat("Foo!", x) 
} 

foo.baz <- function(x) { 
    cat("Baz!", x) 
} 

# does not propagate the operations carried out `foo` 
foo(a) 
foo(b) 
+2

Auch nicht elegant, wenn, würde ich wählen, nur den offensichtlichen Weg und neu eingeben sowohl 'foo.bar' und' foo.baz' die Vorverarbeitung Teils. Alternativ definieren Sie eine Funktion, die den gemeinsamen Teil ausführt (ohne sie zu exportieren): '.preprocess <-function (x) #do stuff 'und dann' foo.bar <-function (x) {x <-. Preprocess (x) ; #do andere Sachen} 'und das selbe für' foo.baz'. – nicola

Antwort

12

1) Schicht foo auf der tatsächlichen generic ändern foo den vorläufigen Code auszuführen und foo_ eine neue generische wie gezeigt aufrufen. Benennen Sie foo.bar und foo.baz-foo_.bar und foo_.baz jeweils so, dass wir mit links sind (habe auch Zeilenumbrüche zum Beispiel):

foo <- function(x) { 
    x <- x * 10 
    foo_(x) 
} 

foo_ <- function(x) UseMethod("foo_") 

foo_.bar <- function(x) cat("Foo!", x, "\n") 
foo_.baz <- function(x) cat("Baz!", x, "\n") 

es jetzt testen:

a <- structure(1:5, class="bar") 
b <- structure(6:10, class="baz") 

foo(a) 
## Foo! 10 20 30 40 50 
foo(b) 
## Baz! 60 70 80 90 100 

Ein Beispiel für diese in ein weit verbreitetes Paket finden Sie in der Quelle dplyr::mutate

2) NextMethod Eine andere Möglichkeit wäre, jedem Objekt eine Klasse zu geben Vektor von zwei Klassen mit "foo" machte eine Unterklasse von "bar" im Fall von a und von "baz" im Fall von b. Dann verwenden Sie NextMethod. Lösung (1) scheint einfacher und es mag seltsam erscheinen, dass "foo" ist eine Unterklasse von beiden "bar" und "baz" aber hier ist ein Beispiel für diese ein für alle Fälle:

foo <- function(x) UseMethod("foo") 

foo.foo <- function(x) { 
    x <- x * 10 
    NextMethod() 
} 
foo.bar <- function(x) cat("Foo!", x, "\n") 
foo.baz <- function(x) cat("Baz!", x, "\n") 

-Test es unter Hinweis darauf, dass wir die Definitionen geändert haben a und b, so dass sie mit diesem Ansatz arbeiten:

a <- structure(1:5, class= c("foo", "bar")) 
b <- structure(6:10, class = c("foo", "baz")) 

foo(a) 
## Foo! 10 20 30 40 50 
foo(b) 
## Baz! 60 70 80 90 100 
Verwandte Themen