[Обновление] Мой первоначальный анализ был правильным, но выводы были неверными :) Давайте сделаем выводы после анализа.
Вот код, демонстрирующий эффекты:
x <- lapply(1:3, function(x) sys.frame(sys.nframe()))
x[[1]] # An environment
x[[2]] # Another environment
x[[3]] # Yet nother environment
x[[1]]$x # 3!!! (should be 1)
x[[2]]$x # 3!! (should be 2)
x[[3]]$x # 3 as expected
# Accessing the variable within the function will "fix" the weird behavior:
x <- lapply(1:3, function(x) {x; sys.frame(sys.nframe())})
x[[1]]$x # 1
x[[2]]$x # 2
x[[3]]$x # 3
Так что обходной путь в вашем случае:
f <- function(a, b) { a;b; function(x) a*x + b }
Кстати, как отмечает @James, есть функция force
, которая делает доступ к переменной более явным:
f <- function(a, b) { force(a);force(b); function(x) a*x + b }
Выводы
Ну, как отметили @mbq и @hadley, это связано с ленивой оценкой. Это проще показать с помощью простого цикла for:
fs <- list(); for(i in 1:2) fs[[i]] <- f(a[[i]], b[[i]])
Аргумент функции f
x
будет не получить значение из a[[i]]
(то есть 0
), но все выражение и среда, в которой существуют a
и i
. Когда вы получаете доступ к x
, он оценивается и поэтому использует i
во время оценки. Если цикл for перешел с момента вызова на f
, вы получите «неправильный» результат ...
Изначально я сказал, что это из-за ошибки в *apply
, которой это не так. ... но так как я ненавижу ошибаться, я могу указать, что * применение имеет ошибку (или, возможно, больше несоответствия) в следующих случаях:
lapply(11:12, function(x) sys.call())
#[[1]]
#FUN(11:12[[1L]], ...)
#
#[[2]]
#FUN(11:12[[2L]], ...)
lapply(11:12, function(x) function() x)[[1]]() # 12
lapply(11:12, function(x) function() x)[[2]]() # 12
Как вы видите выше, lapply
код говорит , что вызывает функцию с 11:12[[1L]]
. Если вы оцените это «позже», вы должны по-прежнему получить значение 11
- но на самом деле вы получите 12
!
Это , вероятно, из-за того, что lapply
реализован в коде C для повышения производительности и небольшого обмана, поэтому отображаемое выражение не является выражением, которое оценивается - ergo, a ошибка ...
QED