2014-09-23 8 views
5

In meiner nicht enden wollende Suche zu überprüfen, Dinge zu brechen, betrachten:wie Formalen modifizierte Funktion

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

R ordnungsgemäß überprüfen meine definierte Funktion für illegal Formalen.

Aber wenn ich manuell Foul Dinge:

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

Dann werde ich nur unter bestimmten Umständen herausfinden, dass etwas ungültig ist. ffoo(3,4,5,6) wird ordnungsgemäß ausgeführt (obwohl wahrscheinlich nicht die Antwort, die ich erwartet habe), wie auch ffoo(y=3,a=2); während ffoo(x=5,y=3,a=2) wird einen Fehler über mehrdeutige Argumentnamen zu werfen.

Also: gibt es irgendwelche base-R oder erweiterte Dienstprogramm-Paket mit einer Funktion zu tun 'Vernunft' Prüfung auf die formals einer bestehenden Funktion?

+1

ich keine R-Funktion finden können, aber Sie können die C lesen Code bei [src/main/gram.y] (https://github.com/wch/r-source/blob/cf829c12299b8571cd67e9d8aae88ac31450c73c/src/main/gram.y). Suche nach der Funktion 'CheckFormalArgs()' – Andrie

+1

@RichardScriven Nein, ich habe deine Antwort akzeptiert. Meine letzte Lösung bestand darin, die tatsächlichen Namen in 'formals' zu überprüfen und aus den Matches eine' do.call' zu erstellen. Ich poste das als eine "Antwort-Erweiterung" –

Antwort

4

Edit:

Wenn Sie einfach nur für duplizierte Argumente überprüfen möchten, können Sie dies tun:

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

Wie Hadley unten in seinem zweiten Kommentar erwähnt wird dput() nicht geben garantiert Sie eine gute/vollständige Darstellung einer Funktion, so kann es Funktionen geben, für die der in meiner ursprünglichen Antwort beschriebene Ansatz fehlschlägt.


Ursprüngliche Antwort:

Wie bei in the C code pointed to by Andrie angedeutet ist, ist dies offensichtlich eine Überprüfung, dass R durchführt, während (nicht Auswertung) einen Aufruf an function() Parsen. Deshalb konnten Sie die Überprüfung mit Ihrem Anruf zu formals<- umgehen, und deshalb vermeidet das folgende (zum Beispiel) auch, überprüft zu werden. In beiden Fällen wird die Funktion geändert/erstellt, ohne einen Aufruf an function() zu analysieren.

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

R Parsing Maschinen nicht typischerweise in den Benutzer sichtbaren R-Funktionen ausgesetzt, so würde ich denke, es gibt keine fertige Funktion R-Funktion diese Prüfung durchzuführen. Sie könnten jedoch genau die gleichen Überprüfungen durchführen, die R ausführt, wenn Sie den Ausdruck quellen oder ihn an einer Befehlszeile eingeben, indem Sie die Funktionsdefinition in ihre Zeichendarstellung konvertieren und dann versuchen, sie erneut zu analysieren.

Hier ist die allgemeine Idee:

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

den Scheck als Funktion tun, so etwas zu wickeln:

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

Warum nicht einfach auf 'dupliziert (Namen (formals (ffoo)))' '? – hadley

+0

@ hadley-- Das (oder eigentlich 'any (duplicated (methods :: formalArgs (" ffoo ")))) war auch mein erster Gedanke, aber ich entschied mich, eine Lösung zu geben, die jedes andere potentielle Unbekannte- to-me prüft, ob R funktioniert. (Deshalb wird in meiner Antwort erwähnt, dass "genau die gleichen Prüfungen wie R [...]" durchgeführt werden) –

+0

Das Problem ist, dass Sie gegen 'dput()' handeln, was Ihnen eine gute Darstellung der Funktion - I gibt Ich habe in der Vergangenheit genug Probleme gehabt, dass ich nicht sehr darauf vertraue. – hadley

Verwandte Themen