Search code examples
robjectr-s4slot

Accessing and modifying arbitrarily deep nested S4 slots


Consider a recursively constructed and arbitrarily deep nested S4 object:

setClass("person", representation(name = "character", child = "ANY"), prototype(name = "", child = NA_real_))
createGeneology <- function(children){
  object <- new("person", name = children[1])
  if(length(children) > 1) object@child <- createGeneology(children[2:length(children)])
  return(object)
}

object <- createGeneology(children = c("Arthur", "Aiden", "Adalyn", "Ava", "Aaron", "Andy"))

In a real-world situation, slots in each layer have some dependency on the layer(s) below. In this situation, it's just a static family tree.

I can directly access and modify slots by typing out the path:

differentKid <- new("person", name = "Logan")
genIV <- object@child@child@child
object@child@child@child <- differentKid

How can this be done dynamically (without typing out an arbitrary number of @child elements?)

I can access the object dynamically by constructing a string and evaluating it with parse, but this trick does not work for modifying the object as eval tries to parse the result as an array:

str <- "object@child@child@child"
genIV <- eval(parse(text = str))

do.call doesn't work:

do.call("<-", list(eval(parse(text = str)), "new('Person', name = 'Logan')"))

assign doesn't work, get doesn't work, so is this just bad practice, is there a better way to do this, or is there something I'm missing?

I've seen similar questions on Stack Overflow but they didn't deal with S4 objects (which are handled a bit differently than lists and arrays).


Solution

  • Still happy to hear if anyone has thoughts. In the meantime, I've been unable to find a way to dynamically access and modify deep recursive layers in an S4 object. Rather, the best solution was to recursively collapse the object into a list of layers.

    Due to the memory overhead of collapsing layers in a class-specific as.list operation, I've decided to go for a list of objects while enforcing relationships between consecutive layers.