Enclosing variables within for loop

前端 未结 3 1217
终归单人心
终归单人心 2020-12-06 13:09

So consider the following chunk of code which does not work as most people might expect it to

#cartoon example
a <- c(3,7,11)
f <- list()

#manual ini         


        
相关标签:
3条回答
  • 2020-12-06 13:45

    This isn't a complete answer, partly because I'm not sure exactly what the question is (even though I found it quite interesting!).

    Instead, I'll just present two alternative for-loops that do work. They've helped clarify the issues in my mind (in particular by helping me to understand for the first time why force() does anything at all in a call to lapply()). I hope they'll help you as well.

    First, here is one that's a much closer equivalent of your properly function lapply() call, and which works for the same reason that it does:

    a <- c(3,7,11)
    f <- list()
    
    ## `for` loop equivalent of:
    ## f <- lapply(1:3, function(i) {force(i); function(x) a[i]+x})
    for(i in 1:3) {
        f[[i]] <- {X <- function(i) {force(i); function(x) a[i]+x}; X(i)}
    }
    f[[1]](1)
    # [1] 4
    

    Second, here is one that does use local() but doesn't (strictly- or literally-speaking) rename i. It does, though, "rescope" it, by adding a copy of it to the local environment. In one sense, it's only trivially different from your functioning for-loop, but by focusing attention on i's scope, rather than its name, I think it helps shed light on the real issues underlying your question.

    a <- c(3,7,11)
    f <- list()
    
    for(i in 1:3) {
       f[[i]] <- local({i<-i; function(x) a[i]+x})
    }
    f[[1]](1)
    # [1] 4
    
    0 讨论(0)
  • 2020-12-06 13:56

    Will this approach work for you?

    ff<-list()
    for(i in 1:3) {
        fillit <- parse(text=paste0('a[',i,']+x' ))
       ff[[i]] <- function(x) ''
       body(ff[[i]])[1]<-fillit
    }
    

    It's sort of a lower-level way to construct a function, but it does work "as you want it to."

    0 讨论(0)
  • 2020-12-06 14:06

    An alternative for force() that would work in a for-loop local environment is

    capture <- function(...) {
        vars<-sapply(substitute(...()), deparse); 
        pf <- parent.frame(); 
        Map(assign, vars, mget(vars, envir=pf, inherits = TRUE), MoreArgs=list(envir=pf))
     }
    

    Which can then be used like

    for(i in 1:3) {
        f[[i]] <- local({capture(i); function(x) a[i]+x})
    }
    

    (Taken from the comments in Josh's answer above)

    0 讨论(0)
提交回复
热议问题