Automating assignment in initialize() methods for Reference Classes in R
Asked Answered
D

1

9

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.

Dirt answered 13/4, 2011 at 19:44 Comment(0)
I
9

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().

Interoffice answered 14/4, 2011 at 0:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.