R scope: force variable substitution in function without local environment

前端 未结 3 429
無奈伤痛
無奈伤痛 2021-01-03 05:47

I\'m defining functions in a loop and trying to force evaluation of a loop variable without having to carry around a private environment.

Example: a set of functions

相关标签:
3条回答
  • 2021-01-03 06:16

    Unfortunately base R lacks a function for making functions by hand, but pryr supplies make_function:

    library(pryr)
    
    handlers <- list()
    for (i in 1:6) {
      body <- substitute(message(i), list(i = i))
      f <- make_function(alist(), body)
    
      handlers[[paste0('h', i)]] <- f
    }
    

    Note the use of substitute to manually modify a quoted call.

    Another cool (IMO!) function in pryr is unenclose, which unencloses a function by substituting in the variables defined in the enclosing environment:

    msg <- function(i) {
        force(i)
        function () message(i)
    }
    msg(1)
    # function () message(i)
    # <environment: 0x102dc6ca0>
    unenclose(msg(1))
    # function () 
    # message(1)
    

    But their really is no downside to using the original closure.

    0 讨论(0)
  • 2021-01-03 06:27

    Here are some approaches that use body<-

    You could use bquote

    handlers <- list()
    
    for (i in 1:6) {
      handlers[[paste0('h', i)]] <- function () {}
      body( handlers[[paste0('h', i)]]) <- bquote(message(.(i)))
    }
    
    handlers$h1
    ## function () 
    ##   message(1L)
    

    or substitute

    for (i in 1:6) {
      handlers[[paste0('h', i)]] <- function () {}
      body( handlers[[paste0('h', i)]]) <- substitute(message(i), list(i=i))
    }
    
    0 讨论(0)
  • 2021-01-03 06:37

    Here are two ways. They are the same except for the ## line in each:

    formals<-

    handlers <- list()
    f <- function() message(i)
    for (i in 1:6) { 
       formals(f) <- list(i = i) ##
       handlers[[paste0('h', i)]] <- f 
    }
    

    trace

    handlers <- list()
    f <- function() message(i)
    for (i in 1:6) { 
       trace(f, bquote(i <- .(i)), print = FALSE) ##
       handlers[[paste0('h', i)]] <- f 
    }
    
    0 讨论(0)
提交回复
热议问题