2014-09-25 7 views
6

Ich verwende die folgenden in einem Paket konstruieren,do.call Umgebung angeben innen Funktion

## two functions in the global environment 
funa <- function(x) x^2 
funb <- function(x) x^3 
## called within a function, fine 
fun_wrap <- function(){ 
    lapply(c('funa', 'funb'), do.call, list(x=3)) 
} 

fun_wrap() 
[[1]] 
[1] 9 

[[2]] 
[1] 27 

aber ich habe durch die Tatsache gerade gebissen, dass es nicht funktioniert, wenn die Funktionen sind in einem andere (lokale) Rahmen,

## same construct, but the functions are local 
fun_wrap1 <- function(){ 
    funa1 <- function(x) x^2 
    funb1 <- function(x) x^3 
    lapply(c('funa1', 'funb1'), do.call, list(x=3)) 
} 
## now it fails 
fun_wrap1() 
##Error in FUN(c("funa1", "funb1")[[1L]], ...) : 
## could not find function "funa1" 

ich habe versucht, envir=parent.frame(2)-do.call() vorbei (nicht funktioniert); Offen gesagt geht die Hilfeseite von ?parent.frame weit über meinen Kopf. Irgendein Hinweis für eine robustere Verwendung von do.call?

Beachten Sie, dass die Liste der Funktionen als ein Zeichenvektor kommt, der von einem anderen Codeabschnitt übergeben wird; Ich bevorzuge es, die Funktionen nicht direkt zu übergeben.

Edit: eine weitere Wendung ... Ich dachte, dass ich das richtige Problem mit meinem Spielzeug Beispiel illustriert hatte, aber der eigentliche Code ich benutze ist etwas anders, in dem Sinne, dass ich telefonieren bin fun_wrap1 innerhalb eine separate Funktion. Die vorgeschlagenen Lösungen scheitern in diesem Zusammenhang.

fun_wrap1 <- function(funs){ 
    lapply(funs, do.call, args=list(x=3), envir=environment()) 
} 

foo <- function(){ 
    funa1 <- function(x) x^2 
    funb1 <- function(x) x^3 
fun_wrap1(c('funa1', 'funb1')) 
} 

foo() 
##Error in FUN(c("funa1", "funb1")[[1L]], ...) : 
## could not find function "funa1" 

(und das gleiche passiert mit dem match.fun Ansatz)

Ich kann es erhalten, indem eine optionale Umgebung fun_wrap1 zu arbeiten,

fun_wrap1 <- function(funs, e=parent.frame()){ 
    lapply(funs, do.call, args=list(x=3), envir=e) 
} 

foo <- function(){ 
    funa1 <- function(x) x^2 
    funb1 <- function(x) x^3 
    fun_wrap1(c('funa1', 'funb1')) 
} 

foo() 

und das ist hoffentlich.

+0

Entschuldigung wegen der ständigen Änderungen, ich hatte es versäumt, das Ziel richtig zu identifizieren, als ich die erste Iteration schrieb. – baptiste

+0

In Ihrem überarbeiteten Beispiel, das fehlschlägt, sollte die neue Funktion geändert werden in: 'fun_wrap1 <- function (funs, envir = parent.frame()) { lapply (Spaß, do.call, args = Liste (x = 3) , envir = envir) } 'Die' foo' Funktion kann so bleiben wie sie ist. –

+0

Danke, ich habe es nach Ihren Ratschlägen geändert. – baptiste

Antwort

5

Dies scheint zu funktionieren, aber ich bin nicht sicher, ob es andere Auswirkungen hat Ich erwäge nicht:

fun_wrap1 <- function(){ 
    funa1 <- function(x) x^2 
    funb1 <- function(x) x^3 
    lapply(c('funa1', 'funb1'), do.call, args=list(x=3), envir=environment()) 
} 

fun_wrap1() 
#[[1]] 
#[1] 9 
# 
#[[2]] 
#[1] 27 

Also das im Wesentlichen äquivalent ist, die lapply Anweisung, wie:

lapply(
     c('funa1', 'funb1'), 
     function(f) do.call(f, args=list(x=3), envir=environment()) 
    ) 
+0

Ich war sehr dicht! Ich lege die Umgebung in die Liste neben 'x = 3' ... – baptiste

+0

@baptiste - es sollte wahrscheinlich' args = list (x = 3) 'sein, um wirklich explizit zu sein. – thelatemail

2

Offensichtlich funktioniert es, wenn wir die Funktionen in fun_wrap2 auswerten. Das Problem mit dem Ansatz in der Frage besteht darin, dass die Zeichenfolgen in Funktionen innerhalb einer der Verarbeitungsfunktionen konvertiert werden, die den Suchpfad ändern.

fun_wrap2 <- function(){ 

    funa1 <- function(x) x^2 
    funb1 <- function(x) x^3 

    nms <- c("funa1", "funb1") 
    funs <- lapply(nms, match.fun) 
    lapply(funs, do.call, list(x=3)) 

} 

fun_wrap2() 
+0

das macht Sinn, danke für die zusätzliche Erklärung.Ich habe inzwischen erkannt, dass mein Problem etwas anders ist, und ich kann diesen Ansatz nicht zur Arbeit bringen (siehe Bearbeiten) – baptiste

+0

Während ich die Hilfe wirklich schätze, habe ich die andere Antwort akzeptiert, da sie die explizite Verabschiedung klargestellt hat die richtige Umgebung, die der Schlüssel zum Problem war. 'match.fun' erreicht das gleiche hier, aber vielleicht nicht so explizit. – baptiste

0

Eine etwas einfachere Version von @ g-Grothen Antwort. Anstatt die Funktionsnamen zu verwenden, fügen wir die Funktionen selbst in die Liste ein, die an lapply übergeben wird.

fun_wrap1 <- function(){ 
    funa1 <- function(x) x^2 
    funb1 <- function(x) x^3 
    lapply(list(funa1, funb1), do.call, list(x=3)) 
} 

fun_wrap1() 
+0

Das war meine ursprüngliche Antwort, aber er gab in den Kommentaren an, dass die Eingabe ein Zeichenvektor von Namen sein muss, also habe ich ihn geändert. –