Reputation: 12564
In R, I'm trying to create one closure for each element of a vector and have it access that specific element when run.
I have a vector of values:
the.vector <- c('a', 'b', 'c')
If I run a function which iterates over the vector, running a simple function which returns each element, the final result would be list('a', 'b', 'c')
. It would look like this (output is simplified for brevity):
Test1 <- function() {
lapply(the.vector, function(element) {
element
})
}
Test1()
list('a', 'b', 'c')
Now, if I iterate over the vector, create a closure that accesses each element, and then iterate over that and run each closure, the result is list('c', 'c', 'c')
(!). It looks like this:
Test2 <- function () {
closures <- lapply(the.vector, function(element) {
function() {
element
}
})
lapply(closures, function(closure) {
closure()
})
}
Test2()
list('c', 'c', 'c')
In summary: I would like the inner closures to reference each of the elements, so that the result of Test2
is the same as Test1
.
I'm pretty sure this is due to the way R resolves variable names, as it does lexical scoping; I'm probably going about it in a dynamic scoping kind of way. However, that doesn't resolve my problem, and I don't know how to do it.
What are the best ways of achieving the desired result?
Upvotes: 4
Views: 374
Reputation: 206207
The problem is that in your Test2 apply loop you're not actually using the variable element
so it remains a "promise" and when that promise is finally resolved when you run the function, you get the last known value for that variable which is "c". The simplest way to fix this is to use the force()
function
Test2 <- function () {
closures <- lapply(the.vector, function(element) {
force(element)
function() {
element
}
})
lapply(closures, function(closure) {
closure()
})
}
Upvotes: 6