R匿名函数:按值捕获变量

时间:2013-04-25 14:04:58

标签: r lambda anonymous-function

我已经定义了一个匿名函数列表,它使用在外部作用域中定义的变量。

funclist <- list()
for(i in 1:5)
{
  funclist[[i]] <- function(x) print(i)
}

funclist[[1]]('foo')

输出结果为:

[1] 5

似乎 i 是通过引用捕获的。我希望它被值捕获,即输出应该是

[1] 1

有没有办法告诉R按价值而非参考来捕捉 i

2 个答案:

答案 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)

这就是你想要的吗?