Возвращение анонимных функций из приложения - что происходит не так?

При попытке создать список похожих функций с помощью lapply, я нахожу, что все функции в списке идентичны и равны тому, что должен быть последним.

Рассмотрим следующее:

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>

При попытке оценить эти функции вы получите одинаковые результаты:

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

Что здесь происходит, и как я могу получить желаемый результат (правильные функции в списке)?

Ответы

Ответ 1

R передает promises, а не сами значения. Обещание принудительно, когда оно сначала оценивается, а не когда оно передается, и к тому времени индекс изменился, если вы используете код в вопросе. Код можно записать следующим образом force обещание во время вызова внешней анонимной функции и дать понять читателю:

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

Ответ 2

Это больше не относится к R 3.2.0!

Соответствующая строка в журнале изменений гласит:

Функции более высокого порядка, такие как функции apply и Reduce(), теперь приводят аргументы к функциям, которые они применяют для устранения нежелательных взаимодействий между ленивой оценкой и захватом переменной в закрытии.

И действительно:

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