2011-12-08 21 views
5

Voglio fare un piccolo pacchetto R con alcune funzioni molto semplici. La letteratura che uso è "Creazione di pacchetti R: Un tutorial" e "Scrittura di estensioni R". Anche se ho provato, ma non capisco il concetto di funzioni e metodi generici e come gestire gli argomenti all'interno delle diverse funzioni.Argomenti e classi per scrivere funzioni (generiche) in R

Ecco un piccolo esempio di come il mio codice è simile:

#Make generic function 
f <- function(x,...) UseMethod("newmethod") 

#Default method 
f.default <- function(a,b=5,c=3,...){ 
    out <- a+b+c 
    class(out) <- "fclass" 
} 

# Print method 
print.f <- function(x,...){ 
    cat("Result:") 
    print(x) 
} 

# Summary method 
summary.f <- function(object,...){ 
    res <- object 
    class(res) <- "fsummary" 
    print(res) 
} 

# Plot method 
plot.f <-function(x,p=0.3,...){} 

Ho una funzione chiamata f con un f.default default. In realtà la mia funzione ha bisogno di diversi argomenti (non di loro è definita come x), quindi come devo fare la mia funzione generica? Il metodo di stampa dovrebbe semplicemente stampare l'output di f.default (in questo caso semplice simile all'output di riepilogo). il metodo plot.f usa l'output di f.default e un argomento aggiuntivo (obbligatorio). Come posso scrivere correttamente queste funzioni? I soliti metodi usano argomenti come "oggetto" e "x" ... ma come ho detto non ho bisogno di alcuna variabile x nelle mie funzioni ... Sono un po 'confuso ... forse qualcuno può aiutare.

Se c'è qualcuno là fuori come è disposto ad aiutarmi con questo problema, potrei anche inviare il codice R "reale" (non solo questo esempio fittizio).

+3

I metodi devono essere coerenti con il generico. Se il tuo generico inizia con l'argomento 'x', allora anche i metodi devono. –

risposta

5

Hai in un pasticcio proprio qui ...

In primo luogo, la vostra funzione di costruzione probabilmente non dovrebbe essere un/metodo generico. Qualcosa di simile:

makefclass = function(a,b,c){ 
     l = list(a=a,b=b,c=c) 
     class(l)="fclass" 
     return(l) 
     } 

print.fclass Poi si può scrivere:

print.fclass=function(x,...){ 
    cat("I'm an fclass!") 
    cat("my abc is ",x$a,x$b,x$c,"\n") 
} 

Poi si fanno:

> f=makefclass(1,2,3) 
> f 
I'm an fclass!my abc is 1 2 2 

Speranza che aiuta ...

+0

Ciao, @spacedman, in qualche modo la tua risposta mi confonde ancora di più ... Seguo l'esempio in ["Creazione di pacchetti R: Un tutorial, pagina 7] [1]. Ma finora quello che ho letto il generico deve avere gli stessi argomenti dei metodi e questo è il motivo per cui mi trovo in difficoltà con il mio esempio ... [1]: http://cran.r-project.org/doc/contrib/Leisch-CreatingPackages.pdf – Johannes

+0

"makefclass" isn ' t un generico, non è un metodo, è solo una funzione che restituisce un oggetto fclass.Il solo riferimento ai generici nel mio esempio è che print.fclass è un metodo per la stampa generica.la stampa ha argomenti (x, ...) e così fa print.f class – Spacedman

+0

Grazie mille ... mi sono appena confuso con il generico, ma non ho bisogno di impostare nulla di generico .. Grazie, tutto funziona ora ... – Johannes

3

Ho risolto il tuo codice e inserire alcuni commenti su ciò che ho risolto ...

UPDATE Come sottolineato da @Spacedman, la funzione "costruttore" probabilmente non dovrebbe essere generica. Ma lo terrò qui, quindi vedi come è stata eseguita una funzione generica da.

#Make generic function 
# This is the "constructor" function... 
# ... UseMethod should have the name of the function! 
f <- function(x,...) UseMethod("f") 

#Default method 
# ... The class name should be the same as the constructor 
f.default <- function(a,b=5,c=3,...){ 
    out <- a+b+c 
    class(out) <- "f" 
    out # must return the object out, not the class name! 
} 

# Print method 
# The "f" part of "print.f" must be the same as the class! 
print.f <- function(x,...){ 
    cat("Result for f: ") 
    print(unclass(x)) # Must unclass to avoid infinite recursion 
    # NextMethod(x) # Alternative, but prints the class attribute... 
} 

# Summary method 
# Should return a summary object (and not print it!) 
# Need a unique class for it ("fsummary") 
summary.f <- function(object,...){ 
    res <- object 
    class(res) <- "fsummary" 
    res 
} 

# Now need to print the summary too: 
print.fsummary <- function(x, ...) { 
    cat("f summary!\n") 
    # Nice summary print goes here... 
} 

# Plot method 
plot.f <-function(x,p=0.3,...){ cat("PLOTTING!\n") } 

# Try it out: 

x <- f(3) 
x # print x 

y <- summary(x) # 
y # print summary 

plot(x) 
+0

Hai usato un costruttore generico, che non è necessario ma è utile quando si sta costruendo da diversi tipi di argomenti, in modo che f (onething) faccia una "f" a seconda di cosa sia "onething". È probabilmente il tipo di funzionalità che potresti voler inserire nei metodi "as.f()" e mantenere il costruttore abbastanza specializzato. YMMV. – Spacedman

+0

@Spacedman - Buon punto.Sono d'accordo che i costruttori dovrebbero essere non generici nella maggior parte dei casi. Ho aggiornato la mia risposta. – Tommy

Problemi correlati