[Cập nhật] phân tích ban đầu của tôi là đúng nhưng kết luận là sai :) Hãy đi đến kết luận sau khi phân tích.
Dưới đây là một số mã chứng minh tác dụng:
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
Vì vậy, các công việc xung quanh trong trường hợp của bạn:
f <- function(a, b) { a;b; function(x) a*x + b }
Btw, như @ James ghi nhận có một chức năng force
mà làm cho truy cập vào một biến rõ ràng hơn:
f <- function(a, b) { force(a);force(b); function(x) a*x + b }
Conclu sions
Vâng, như @mbq và @hadley lưu ý, điều này là do đánh giá lười biếng. Nó dễ dàng hơn để hiển thị với một đơn giản cho vòng lặp:
fs <- list(); for(i in 1:2) fs[[i]] <- f(a[[i]], b[[i]])
Chức năng f
'x
luận s sẽ không nhận được giá trị của a[[i]]
(đó là 0
), nhưng toàn bộ biểu và môi trường có a
và i
tồn tại. Khi bạn truy cập x
, nó được đánh giá và do đó sử dụng i
tại thời điểm đánh giá. Nếu vòng lặp for đã di chuyển kể từ khi gọi tới số f
, bạn nhận được kết quả "sai" ...
Ban đầu tôi đã nói rằng điều này là do lỗi trong *apply
, không phải vậy. ... nhưng kể từ khi tôi ghét phải là sai, tôi có thể chỉ ra rằng * Áp dụng KHÔNG có một lỗi (hoặc có lẽ nhiều hơn một sự mâu thuẫn) trong những trường hợp:
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
Như bạn thấy ở trên, mã lapply
nói, nó gọi hàm là 11:12[[1L]]
. Nếu bạn đánh giá rằng "sau" bạn nên vẫn nhận được giá trị 11
- nhưng bạn thực sự nhận được 12
!
Đây là lẽ do thực tế rằng lapply
được thực hiện trong mã C vì lý do hiệu suất và ăn gian một chút, vì vậy biểu thức mà nó cho thấy không phải là sự biểu hiện đó được đánh giá - ergo, một lỗi ...
QED
+1 để tìm hành vi kỳ lạ này! Tôi yêu những điều này :-) – Tommy
Có thể không phải là một điều * áp dụng: 'fs <- list(); cho (i trong 1: 2) fs [[i]] <- f (a [[i]], b [[i]]) 'làm điều tương tự. – pete