Juan Carlos Coto
Juan Carlos Coto

Reputation: 12564

How to create one closure for each of the elements in a vector in R?

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

Answers (1)

MrFlick
MrFlick

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

Related Questions