title: Copying global variable to local variable at time of function definition
body: <p>I am currently dealing with an issue in R, where I am trying to define functions in a <code>for</code> loop using the value of global values at the time the functions are defined. However every attempt seems to have some issue.</p>
  
  <p><strong>Attempt 1:</strong>
  The first attempt was basic.</p>
  
  <pre><code>models = list()
  nodes  = list(c(1), c(2))
  d      = data.frame(CD=c(1,2))
  for (i in 1:2) {
      models[[i]]         = list()
      models[[i]]$outcome = function(dat) {dat$CD %in% nodes[[i]]}
  
      cat(sprintf('\nIteration %d\n', i))
  
      cat(sprintf('\tModel %d outcome\n', i))
      print(models[[i]]$outcome(d))
  
      cat(sprintf('\tModel 1 outcome\n'))
      print(models[[1]]$outcome(d))
  }
  cat('\nFinal model 1 outcome')
  print(models[[1]]$outcome(d))
  
  cat('\nFinal model 2 outcome')
  print(models[[2]]$outcome(d))
  </code></pre>
  
  <p>This gives the outcomes</p>
  
  <pre><code>Iteration 1
      Model 1 outcome
  [1]  TRUE FALSE
      Model 1 outcome
  [1]  TRUE FALSE
  
  Iteration 2
      Model 2 outcome
  [1] FALSE  TRUE
      Model 1 outcome
  [1] FALSE  TRUE
  
  Final model 1 outcome
  [1] FALSE  TRUE
  
  Final model 2 outcome
  [1] FALSE  TRUE
  </code></pre>
  
  <p>The function <code>models[[1]]$outcome</code> has been modified from the first iteration to the second as it depended on <code>nodes[[i]]</code> which has been changed, fair enough.</p>
  
  <p><strong>Attempt 2:</strong>
  The second attempt was using a partial function in <code>pryr</code>.</p>
  
  <pre><code>library(pryr)
  f = function(dat, x) {dat$CD %in% x}
  models = list()
  nodes  = list(c(1), c(2))
  d      = data.frame(CD=c(1,2))
  for (i in 1:2) {
      models[[i]]         = list()
      models[[i]]$outcome = partial(f, x=nodes[[i]])
  
      cat(sprintf('\nIteration %d\n', i))
  
      cat(sprintf('\tModel %d outcome\n', i))
      print(models[[i]]$outcome(d))
  
      cat(sprintf('\tModel 1 outcome\n'))
      print(models[[1]]$outcome(d))
  }
  cat('\nFinal model 1 outcome')
  print(models[[1]]$outcome(d))
  
  cat('\nFinal model 2 outcome')
  print(models[[2]]$outcome(d))
  </code></pre>
  
  <p>This gives the same outcome</p>
  
  <pre><code>Iteration 1
      Model 1 outcome
  [1]  TRUE FALSE
      Model 1 outcome
  [1]  TRUE FALSE
  
  Iteration 2
      Model 2 outcome
  [1] FALSE  TRUE
      Model 1 outcome
  [1] FALSE  TRUE
  
  Final model 1 outcome
  [1] FALSE  TRUE
  
  Final model 2 outcome
  [1] FALSE  TRUE
  </code></pre>
  
  <p>This to me seems counter-intuitive. I would have expected a partial function to have copied the values of the inputs at the time the function was defined.</p>
  
  <p><strong>Attempt 3:</strong> I now attempted to use function closures.</p>
  
  <pre><code>f = function(x) { 
      g = function(dat) {dat$CD %in% x}
  } 
  models = list()
  nodes  = list(c(1), c(2))
  d      = data.frame(CD=c(1,2))
  for (i in 1:2) {
      models[[i]]         = list()
      models[[i]]$outcome = f(nodes[[i]])
  
      cat(sprintf('\nIteration %d\n', i))
  
      cat(sprintf('\tModel %d outcome\n', i))
      print(models[[i]]$outcome(d))
  
      cat(sprintf('\tModel 1 outcome\n'))
      print(models[[1]]$outcome(d))
  }
  cat('\nFinal model 1 outcome')
  print(models[[1]]$outcome(d))
  
  cat('\nFinal model 2 outcome')
  print(models[[2]]$outcome(d))
  </code></pre>
  
  <p>This gave the outcome</p>
  
  <pre><code>Iteration 1
      Model 1 outcome
  [1]  TRUE FALSE
      Model 1 outcome
  [1]  TRUE FALSE
  
  Iteration 2
      Model 2 outcome
  [1] FALSE  TRUE
      Model 1 outcome
  [1]  TRUE FALSE
  
  
  Final model 1 outcome
  [1] TRUE   FALSE
  
  Final model 2 outcome
  [1] FALSE  TRUE
  </code></pre>
  
  <p>It seems like we are finally getting somewhere. However there are two issues. Firstly something strange happens if we comment the print statements in the for loop.</p>
  
  <pre><code>f = function(x) { 
      g = function(dat) {dat$CD %in% x}
  } 
  models = list()
  nodes  = list(c(1), c(2))
  d      = data.frame(CD=c(1,2))
  for (i in 1:2) {
      models[[i]]         = list()
      models[[i]]$outcome = f(nodes[[i]])
  
      #cat(sprintf('\nIteration %d\n', i))
  
      #cat(sprintf('\tModel %d outcome\n', i))
      #print(models[[i]]$outcome(d))
  
      #cat(sprintf('\tModel 1 outcome\n'))
      #print(models[[1]]$outcome(d))
  }
  cat('\nFinal model 1 outcome')
  print(models[[1]]$outcome(d))
  
  cat('\nFinal model 2 outcome')
  print(models[[2]]$outcome(d))
  </code></pre>
  
  <p>We get the results</p>
  
  <pre><code>Final model 1 outcome
  [1] FALSE  TRUE
  
  Final model 2 outcome
  [1] FALSE  TRUE
  </code></pre>
  
  <p>So it seems the prints were causing us to copy the global variable at the time of the print statement (which is what I indirectly wanted). However, more annoyingly, I am running this inside a function and returning the <code>models</code> object. By doing this, the <code>models[[i]]$outcome</code> captures the whole environment it was defined in which means it ends up taking up (unnecessarily) a lot of memory.</p>
  
  <p><strong>Question</strong></p>
  
  <p>What is the correct way to achieve what I am trying to do i.e. copy the global variable at the time of the function definition as opposed to 'pointing' to it, without capturing the whole environment I have defined my function in.</p>