R anonymous function: capture variables by value

北城以北 提交于 2020-02-20 04:42:29

问题


I've defined a list of anonymous functions which use a variable defined in an outer scope.

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

funclist[[1]]('foo')

The output is:

[1] 5

It seems that i is captured by reference. I'd like it to be captured by value, i.e. the output should be

[1] 1

Is there a way to tell R to capture i by value rather than by reference?


回答1:


When you run a for loop, this creates a variable in the environment the loop is run in, and functions created in the loop are also run from this environment. So whenever you run the functions created in this way that use the index value from the loop, they only have access to the final value, and only as long as that varaible remains (try rm(i) and attempting to fun one of the functions in the list).

What you need to do is bind the index value to the function in their own environment. lapply will do this for you automatically. However, there is a gotcha with lazy evaluation. What you have to do is also force the evaluation of i before creating the anonymous function:

funclist <- lapply(1:5, function(i) {force(i); function(x) print(i)})
funclist[[1]]('foo')
[1] 1
funclist[[5]]('foo')
[1] 5



回答2:


My read on what you want is to store a value inside the function's environment when the function is defined, and then hold onto that value for internal computations.

For that, you want a closure:

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)

Is that what you wanted?



来源:https://stackoverflow.com/questions/16216909/r-anonymous-function-capture-variables-by-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!