Search code examples
rr6

R - R6 - higher order function - scope of enclosing function


I try to create dynamically the initialize function of R6 class. First I create unlocked class definition:

   cls <- R6::R6Class(
       name,
       inherit=TPayload,
       lock_objects=FALSE,
       public=list(
           module=class(tail(Parser$thrift_stack, 1)[[1]])[[1]],
           ttype=ttype
       ))

And somewhere after I add an initialize function:

cls$set("public", 'initialize', init_func_generator(cls, default_spec))

where init_func_generator:

init_func_generator = function(cls, spec) {    
  func = function(...) {
    cat('Hello\n')
  }

  return(func)
}

Executing simple initialize function works when I create an object.

cli$new(name='abc')

However when I try to access 'spec' variable from outside scope of created 'initialize':

init_func_generator = function(cls, spec) {    
  func = function(...) {
    for(s in spec) {
      cat(str(s))
    }
  }

  return(func)
}

I get:

* object 'spec' not found

Is it possible what I try to achieve?


Solution

  • I rewrote my solution to this:

    init_func_generator = function(cls, spec) {
      if(length(spec) == 0) return(function() { })
    
      args <- alist()
      for(s in spec) {
        args[[s[[1]]]] <- s[[2]]
      }
    
      func <- function() {
        argg <- as.list(environment())
        for(arg_name in names(argg)) {
          self[[arg_name]] <- argg[[arg_name]]
        }
      }
      formals(func) <- args
    
      return(func)
    }
    

    So now I can do:

      print(s$Set$new(a_set=1)$a_set)
      [1] 1
    
      print(s$Set$new()$a_set)
      [1] NA
    

    when the spec in this case is [('a_set', NA)]