1

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?

Marek Jagielski
  • 802
  • 10
  • 17
  • just to understand your needs a bit more, why can't you pass in `cls` and `spec` into the inner `func` (.e.g `func = function(cls, spec)`)? – chinsoon12 Mar 05 '18 at 00:53
  • you might need to add `force(cls); force(spec)` before your defintion of `func`. Or you can change the args to your `init_func_generator` to `...` – chinsoon12 Mar 05 '18 at 01:06
  • First, I create a R6 class definition basing on specification (thrift). I want that someone who creates an object can pass in constructor some values that will set the fields. 'spec' contains default values of those fields. In constructor initialize, I want to set fields values either given in arguments or default that were in spec. I want to achieve similar mechanism as is here https://github.com/eleme/thriftpy/blob/v0.3.9/thriftpy/thrift.py – Marek Jagielski Mar 05 '18 at 04:31
  • force didn't help; in fact I am using 'spec' without problems in init_func_generator: init_func_generator = function(cls, spec) { if(length(spec) == 0) return(function() { }) ... before definition of inner function. – Marek Jagielski Mar 05 '18 at 04:49

1 Answers1

0

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)]

Marek Jagielski
  • 802
  • 10
  • 17