2014-09-23 14 views
5

Nella mia ricerca senza fine di rompere le cose, considerare:formali di funzioni come controllare modificati

gbar<-function(x,y,x,a) x+2*y-4*a 
Error: repeated formal argument 'x' on line 1 

R verifiche correttamente la mia funzione definita per formali illegali.

Ma se io le cose immonde manualmente:

ffoo<-function(x,y,a) x+2*y-4*a 
formals(ffoo)<-c(x=7, formals(ffoo)) 

allora io solo scoprire in determinate circostanze che qualcosa non è valido. ffoo(3,4,5,6) verrà eseguito correttamente (anche se probabilmente non mi sta dando la risposta che mi aspettavo), come lo sarà ffoo(y=3,a=2); mentre ffoo(x=5,y=3,a=2) genererà un errore sui nomi di argomenti ambigui.

Quindi: esiste un base-R o un pacchetto di utilità avanzato con una funzione per eseguire il controllo di 'integrità' sullo formals di una funzione esistente?

+1

non riesco a trovare una funzione R, ma si può leggere la C codice in [src/main/gram.y] (https://github.com/wch/r-source/blob/cf829c12299b8571cd67e9d8aae88ac31450c73c/src/main/gram.y). Cerca la funzione 'CheckFormalArgs()' – Andrie

+1

@RichardScriven No, ho accettato la risposta. La mia soluzione finale era di controllare i nomi effettivi in ​​'formals' e creare un' do.call' tra le partite. Lo posterò come "risposta-estensione" –

risposta

4

Edit:

Se si vuole semplicemente verificare la presenza di argomenti duplicati, si può fare questo:

any(duplicated(names(formals(ffoo)))) 
# [1] TRUE 

Come Hadley cita nel suo secondo commento qui sotto, dput() non è garantito per dare è una buona/completa rappresentazione di una funzione, quindi potrebbero esserci delle funzioni per le quali l'approccio descritto nella mia risposta originale (lasciato al suo posto sotto) non funziona.


risposta originale:

Come accennato in the C code pointed to by Andrie, questo è apparentemente un controllo che R esegue durante l'analisi (non valutare) una chiamata a function(). Ecco perché sei stato in grado di eludere l'assegno con la tua chiamata allo formals<-, ed è per questo che il seguente (ad esempio) evita anche di essere controllato. In entrambi i casi, la funzione viene modificata/creata senza analizzare una chiamata a function(). macchinari analisi

eval(call("function", formals(ffoo), body(ffoo))) 
# function (x = 7, x, y, a) 
# x + 2 * y - 4 * a 

di R non è in genere esposto nelle funzioni R visibili dall'utente, in modo direi non c'è Funzione R ready-made per eseguire questo controllo. Tuttavia, è possibile eseguire esattamente lo stesso set di controlli che fa R quando si genera l'espressione o immesso in una riga di comando convertendo la definizione della funzione nella sua rappresentazione di carattere e quindi tentando di analizzarla nuovamente.

Ecco l'idea generale:

parse(text = capture.output(dput(ffoo))) 
# Error in parse(text = capture.output(dput(ffoo))) : 
# repeated formal argument 'x' on line 1 

Per avvolgere il check-up in funzione fare qualcosa del genere:

isParseableFunction <- function(x) { 
    tryCatch(is.function(x) & 
      is.expression(parse(text = capture.output(dput(x)))), 
      error = function(e) FALSE) 
} 

isParseableFunction(data.frame) 
# [1] TRUE 
isParseableFunction(mean) 
# [1] TRUE 
isParseableFunction(ffoo) 
# [1] FALSE 
isParseableFunction(99) 
# [1] FALSE 
+0

Perché non guardare solo 'duplicato (nomi (formali (ffoo))' '? – hadley

+0

@ hadley-- Questo (o, in realtà, 'any (duplicato (metodi :: formalArgs (" ffoo ")))') è stato anche il mio primo pensiero, ma ho deciso di dare una soluzione che avrebbe implementato qualsiasi altra potenziale sconosciuta- to-me controlla che R funzioni. (Ecco perché la mia risposta dice di eseguire "lo stesso identico set di controlli che R fa [...]") –

+0

Il problema è che si sta negoziando con 'dput()' dando una buona rappresentazione della funzione - I Ho avuto abbastanza problemi in passato, che non mi fido molto. – hadley

Problemi correlati