我已经定义了一个匿名函数列表,它使用在外部作用域中定义的变量。
funclist <- list()
for(i in 1:5)
{
funclist[[i]] <- function(x) print(i)
}
funclist[[1]]('foo')
输出结果为:
[1] 5
似乎 i 是通过引用捕获的。我希望它被值捕获,即输出应该是
[1] 1
有没有办法告诉R按价值而非参考来捕捉 i ?
答案 0 :(得分:6)
当您运行for
循环时,这将在运行循环的环境中创建变量,并且循环中创建的函数也将从此环境运行。因此,每当您运行以这种方式创建的函数使用循环中的索引值时,它们只能访问最终值,并且只有该变量仍然存在(尝试rm(i)
并尝试使其中一个列表中的函数。)
您需要做的是将索引值绑定到自己环境中的函数。 lapply
会自动为您执行此操作。然而,有一个懒惰的评估陷阱。在创建匿名函数之前,您还必须force
评估i
:
funclist <- lapply(1:5, function(i) {force(i); function(x) print(i)})
funclist[[1]]('foo')
[1] 1
funclist[[5]]('foo')
[1] 5
答案 1 :(得分:3)
我想了解你想要的是在定义函数时在函数环境中存储一个值,然后保留该值用于内部计算。
为此,你需要一个闭包:
i <- 3
test <- local({
i <- i
function(x) x[i]
})
test(letters[1:5]) # returns 'c'
i <- 5
test(letters[1:5]) # still returns 'c' (i.e. i is local to the test closure)
这就是你想要的吗?