Ответ 1
[Обновить] Мой первоначальный анализ был правильным, но выводы были неправильными:) Пусть дойдет до выводов после анализа.
Здесь показан код, демонстрирующий эффекты:
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 }
Btw, как отмечает @James, есть функция force
, которая делает доступ к переменной более явной:
f <- function(a, b) { force(a);force(b); function(x) a*x + b }
Выводы
Ну, как заметили @mbq и @hadley, это связано с ленивой оценкой. Легче показать с помощью простой петли:
fs <- list(); for(i in 1:2) fs[[i]] <- f(a[[i]], b[[i]])
Аргумент f
x
функции не получает значение a[[i]]
(которое равно 0
), но все выражение и среда, где a
и i
существуют. Когда вы обращаетесь к x
, он получает оценку и поэтому использует i
во время оценки. Если for-loop перемещается с момента вызова на f
, вы получаете "неправильный" результат...
Первоначально я сказал, что это произошло из-за ошибки в *apply
, чего нет.... но поскольку я ненавижу ошибаться, я могу указать, что * apply У DOES есть ошибка (или, возможно, больше несогласованности) в этих случаях:
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, ошибка...
КЭД