2015-12-29 31 views
8

Ho una funzione generica denominata foo. Funziona in modo diverso sulle classi bar e baz ma esiste una pre-elaborazione condivisa che deve essere eseguita una sola volta. Qual è il modo idiomatico di portarlo fuori?R pattern per modificare gli argomenti passati alla funzione generica

Nel mio stupido esempio qui sotto, voglio moltiplicare l'oggetto che viene passato al generico di 10. Tuttavia, quando viene chiamato il metodo, il valore originale viene stampato sulla console. Ho letto la definizione della lingua e so che il pattern sottostante non funziona. La mia domanda è: dove o come dovrei gestire l'elaborazione condivisa di argomenti generici prima di chiamare il metodo?

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

Anche se non elegante, vorrei solo scegliere il percorso evidente e digitare nuovamente la parte di pre-elaborazione sia in '' foo.bar' e foo.baz'. In alternativa, definire una funzione che fa la parte comune (senza esportarla): '.preprocess <-function (x) #do stuff' e quindi' foo.bar <-function (x) {x <-. Preprocess (x) ; #do altre cose} 'e lo stesso per' foo.baz'. – nicola

risposta

12

1) Strato foo in cima effettivo generico Change foo per eseguire il codice preliminare e richiamare foo_ un nuovo generico come mostrato. Rinomina foo.bar e foo.baz-foo_.bar e foo_.baz rispettivamente in modo che ci rimane (anche aggiunto nuove righe per l'esempio):

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

Ora provarlo:

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 

Per un esempio di questo in un pacchetto ampiamente utilizzato vedere la fonte di dplyr::mutate

2) NextMethod Un altro modo sarebbe quello di assegnare a ogni oggetto una classe il vettore di due classi con "foo" ha creato una sottoclasse di "bar" nel caso di a e di "baz" nel caso di b. Quindi utilizzare NextMethod. Soluzione (1) sembra più semplice e può sembrare strano che "foo" è una sottoclasse di entrambi "bar" e "baz" ma qui è un esempio di questo nel caso in cui:

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 è notare che abbiamo cambiato le definizioni di a e b in modo che funzionino con questo approccio:

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 
Problemi correlati