2010-03-16 17 views
41

Diciamo che abbiamo la seguente funzione:Quali sono i modi per modificare una funzione in R?

foo <- function(x) 
{ 
    line1 <- x 
    line2 <- 0 
    line3 <- line1 + line2 
    return(line3) 
} 

E che vogliamo cambiare la seconda linea di essere:

line2 <- 2 

Come l'hai fatto?

Un modo è quello di utilizzare

fix(foo) 

e cambiare la funzione.

Un altro modo è di scrivere nuovamente la funzione.

C'è un altro modo? (Ricorda, l'operazione era di cambiare solo la seconda riga)

Quello che vorrei è in qualche modo rappresentare la funzione come un vettore di stringhe (beh, caratteri), quindi cambiare uno dei suoi valori, e quindi girare in una funzione di nuovo.

+1

E non è qualcosa che si può fare passando un parametro ad una funzione? .. Si noti che è anche possibile passare le funzioni come parametri. –

+2

Ciao Leo - la domanda è per quando voglio cambiare una funzione fatta da qualcun altro, ma all'interno del codice non è necessario copiare l'intera funzione. –

+0

se hai bisogno di modificare una funzione "interna", ho trovato molto utili i consigli e gli snippet seguenti: [nabble: how-to-override-replace-a-function-in-a-package-namespace] (http: // r.789695.n4.nabble.com/how-to-override-replace-a-function-in-a-package-namespace-td866337.html) –

risposta

21

Oppure dai un'occhiata alla funzione di debug trace(). Probabilmente non è esattamente quello che stai cercando, ma ti permette di giocare con le modifiche e ha la bella funzione che puoi sempre tornare alla tua funzione originale con untrace(). trace() fa parte del pacchetto base e viene fornito con una pagina di aiuto completa e completa.

Inizia chiamando il numero as.list (body(foo)) per vedere tutte le linee del tuo codice.

as.list(body(foo)) 
[[1]] 
`{` 

[[2]] 
line1 <- x 

[[3]] 
line2 <- 0 

[[4]] 
line3 <- line1 + line2 

[[5]] 
return(line3) 

Quindi è sufficiente definire cosa aggiungere alla funzione e dove posizionarlo definendo gli argomenti in trace().

trace (foo, quote(line2 <- 2), at=4) 
foo (2) 
[1] 4 

ho detto all'inizio che trace() potrebbe non essere esattamente quello che stai cercando in quanto non hai davvero cambiare la tua terza riga di codice e invece semplicemente riassegnato il valore all'oggetto line2 nel seguito, inserito linea di codice.Diventa più chiaro se si stampa il codice della funzione ora tracciata

body (foo) 
{ 
    line1 <- x 
    line2 <- 0 
    { 
     .doTrace(line2 <- 2, "step 4") 
     line3 <- line1 + line2 
    } 
    return(line3) 
} 
20

fix è il modo migliore che conosco di fare questo, anche se è possibile anche utilizzare edit e ri-assegnare:

foo <- edit(foo) 

Questo è ciò che fa fix internamente. Potresti voler farlo se volessi riassegnare le tue modifiche a un nome diverso.

7

È possibile utilizzare la funzione 'corpo'. Questa funzione restituisce il corpo della funzione:

fnx = function(a, b) { return(a^2 + 7*a + 9)} 
body(fnx) 
# returns the body of the function 

Quindi un buon modo per 'modifica' una funzione è quella di utilizzare 'corpo' sul lato sinistro di un'istruzione di assegnazione:

body(fnx) = expression({a^2 + 11*a + 4}) 
+1

In realtà è un uso della funzione 'body <-'. –

33
> body(foo)[[3]] <- substitute(line2 <- 2) 
> foo 
function (x) 
{ 
    line1 <- x 
    line2 <- 2 
    line3 <- line1 + line2 
    return(line3) 
} 

(Il "{" è il corpo (foo) [[1]] e ogni linea è un elemento successivo della lista.)

+7

Recentemente sono stato costretto a fare cose simili e una cosa può essere migliorata: puoi andare più in profondità nella lista, quindi per il caso di domanda 'body (foo) [[3]] [[3]] <- 2' funziona e' il sostituto è inutile. – Marek

+0

Grazie. Pensavo che il sostituto fosse necessario per mantenere la modalità dell'espressione come un elemento della lingua. –

+2

Se si sostituisce l'intera linea, allora sì, è necessario. Generalmente: le classi devono corrispondere: il mio modo di lavorare causa che sostituisco numero per numero. Se voglio sostituire, diciamo, 'line2' in' myVariable' e quindi è necessaria la conversione 'as.symbol'. – Marek

15

fixInNamespace è come fix, per le funzioni in un pacchetto (compresi quelli che non sono stati esportati).

Problemi correlati