Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automating assignment in initialize() methods for Reference Classes in R

I'm working with a reference class with a few dozen fields. I've set up an initialize()method that takes a list object in. While some of the fields rely on further computation from list elements, most of the fields are directly assigned from list elements as such:

fieldA <<- list$A
fieldB <<- list$B

I was thinking that it'd be nice to automate this a bit. To give an example in R pseudocode (this example obviously won't work):

for (field in c('A', 'B', 'C', 'D'))
   field <<- list[[field]]

I've tried making a few end runs around the <<- for instance doing something like:

for field in c('A', 'B', 'C', 'D'))
  do.call('<<-' c(field, list[[field]])) 

but no dice.

My guess is that this sort of behavior simply isn't possible in the current incarnation of reference classes, but thought it might be worth seeing if anyone out in SO land knew of a better way to do this.

like image 203
geoffjentry Avatar asked Apr 13 '11 19:04

geoffjentry


1 Answers

Use .self to indicate the instance, and select fields using [[. I'm not 100% sure (but who ever is?) that [[ is strictly legal. I added defaults to lst, so it works when invoked as C$new(), an implicit assumption in S4 that seems likely to bite in a similar way with reference classes.

C <- setRefClass("C",
    fields=list(a="numeric", b="numeric", c="character"),
    methods=list(
      initialize=function(..., lst=list(a=numeric(), b=numeric(), c=character()) 
        {
          directflds <- c("a", "b")
          for (elt in directflds)
              .self[[elt]] <- lst[[elt]]
          .self$c <- as.character(lst[["c"]])
          .self
      }))
c <- C$new(lst=list(a=1, b=2, c=3))

Or leave the option to pass a list or the elements themselves to the user with

B <- setRefClass("B",
    fields=list(a="numeric", b="numeric", c="character"),
    methods=list(
      initialize=function(..., c=character()) {
          callSuper(...)
          .self$c <- as.character(c)
          .self
      }))
b0 <- B$new(a=1, b=2, c=3)
b1 <- do.call(B$new, list(a=1, b=2, c=3))

This also seems to be more tolerant of omitting some values from the call to new().

like image 82
Martin Morgan Avatar answered Nov 10 '22 15:11

Martin Morgan