2013-04-01 8 views
13

Wenn ich versuche, eine Liste von ähnlichen Funktionen mit lapply zu erstellen, finde ich, dass alle Funktionen in der Liste identisch sind und gleich, was das letzte Element sein sollte.Anonyme Funktionen von lapply zurückgeben - was läuft falsch?

Betrachten Sie das folgende:

pow <- function(x,y) x^y 
pl <- lapply(1:3,function(y) function(x) pow(x,y)) 
pl 
[[1]] 
function (x) 
pow(x, y) 
<environment: 0x09ccd5f8> 

[[2]] 
function (x) 
pow(x, y) 
<environment: 0x09ccd6bc> 

[[3]] 
function (x) 
pow(x, y) 
<environment: 0x09ccd780> 

Wenn Sie versuchen, diese Funktionen bewerten Sie identische Ergebnisse erhalten:

pl[[1]](2) 
[1] 8 
pl[[2]](2) 
[1] 8 
pl[[3]](2) 
[1] 8 

Was hier vor sich geht, und wie kann ich das Ergebnis, das ich wünsche (die richtigen Funktionen in der Liste)?

+0

Ich bin nicht sicher, was Ihr Ziel ist. Vielleicht 'pl <- Funktion (x, y) lapply (y, Funktion (y) pow (x, y)); pl (2,1: 3) '? – Roland

+0

Diese Noten von Ross Ihaka (RCore) könnte hilfreich sein (genauer gesagt der Teil zu Lazy Evaluation) www.stat.auckland.ac.nz/~ihaka/downloads/Waikato-WRUG.pdf –

+0

Beachten Sie, dass dies nicht länger wahr, wie von R 3.2.0, siehe meine Antwort unten. – jhin

Antwort

20

R reicht promises, nicht die Werte selbst. Das Versprechen wird erzwungen, wenn es zuerst ausgewertet wird, nicht wenn es übergeben wird. Zu diesem Zeitpunkt hat sich der Index geändert, wenn der Code in der Frage verwendet wird. Der Code kann geschrieben werden, wie auf force folgt an der Zeit, das Versprechen der äußeree anonyme Funktion aufgerufen wird und es den Leser klar zu machen:

pl <- lapply(1:3, function(y) { force(y); function(x) pow(x,y) }) 
+0

Danke, es ist gut zu wissen, wie dieser Fallstrick funktioniert. Das muss ich mir in Zukunft merken. – James

4

Das ist nicht mehr wahr, wie die R 3.2.0!

die entsprechende Zeile in den change log lautet:

Höherwertige Funktionen wie die Funktionen übernehmen und Reduzieren() nun Kraft Argumente zu den Funktionen, die sie anwenden, um unerwünschte Wechselwirkungen zwischen lazy evaluation zu beseitigen und variable Erfassung in Schließungen.

Und in der Tat:

pow <- function(x,y) x^y 
pl <- lapply(1:3,function(y) function(x) pow(x,y)) 
pl[[1]](2) 
# [1] 2 
pl[[2]](2) 
# [1] 4 
pl[[3]](2) 
# [1] 8 
+0

Das sind gute Nachrichten. – James

Verwandte Themen