2013-04-01 7 views
13

Podczas próby utworzenia listy podobnych funkcji przy użyciu lapply, stwierdzam, że wszystkie funkcje na liście są identyczne i równe temu, jaki powinien być końcowy element.Zwracanie anonimowych funkcji lapply - co dzieje się nie tak?

Rozważmy następujący:

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> 

Podczas próby oceny tych funkcji można uzyskać takie same wyniki:

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

Co tu się dzieje i jak mogę uzyskać wynik pragnę (prawidłowe funkcje na liście)?

+0

Nie jestem pewien, co jest twoim celem. Może 'pl <- funkcja (x, y) lapply (y, funkcja (y) pow (x, y)); pl (2,1: 3) '? – Roland

+0

Te notatki autorstwa Rossa Ihaka (RCore) mogą być pomocne (szczególnie część dotycząca Lazy Evaluation) www.stat.auckland.ac.nz/~ihaka/downloads/Waikato-WRUG.pdf –

+0

Pamiętaj, że nie jest to już prawdą R 3.2.0, zobacz moją odpowiedź poniżej. – jhin

Odpowiedz

20

R przechodzi promises, a nie same wartości. Obietnica jest wymuszana, gdy jest ona oceniana po raz pierwszy, a nie wtedy, gdy jest przekazywana, i do tego czasu indeks się zmienił, jeśli użyje się kodu w pytaniu. Kod można zapisać w następujący sposób force obietnicę w czasie zewnętrzna funkcja anonimowa nazywa i uświadomić czytelnika:

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

Dzięki, dobrze jest wiedzieć, jak działa ta pułapka. Będę o tym pamiętać w przyszłości. – James

4

nie jest to już prawdą jako R 3.2.0!

odpowiedniej linii w change log brzmi:

funkcja wyższego rzędu, takich jak zastosowanie funkcji i Reduce() teraz argumenty siły do ​​funkcji, jakie są stosowane w celu wyeliminowania niepożądane interakcje między leniwe oceny i zmienne przechwytywanie w zamknięciach.

I rzeczywiście:

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

To dobra wiadomość. – James

Powiązane problemy