Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In R, how can one make a method of an S4 object that directly adjusts the values inside the slots of that object?

Tags:

oop

r

s4

Is there a way to allow a method of an S4 object to directly adjust the values inside the slots of that object without copying the entire object into memory and having to re-write it to the parent environment at the end of the method? Right now I have an object that has slots where it keeps track of its own state. I call a method that advances it to the next state, but right now it seems like I have to assign() each value (or a copy of the object invoking the method) back to the parent environment. As a result, the object oriented code seems to be running a lot slower than code that simply adjusts the various state variables in a loop.

like image 892
russellpierce Avatar asked Feb 27 '23 12:02

russellpierce


2 Answers

R has three object oriented (OO) systems: S3, S4 and Reference Classes (where the latter were for a while referred to as [[R5]], yet their official name is Reference Classes).

Reference Classes (or refclasses) are new in R 2.12. They fill a long standing need for mutable objects that had previously been filled by non-core packages like R.oo, proto and mutatr. While the core functionality is solid, reference classes are still under active development and some details will change. The most up-to-date documentation for Reference Classes can always be found in ?ReferenceClasses.

There are two main differences between reference classes and S3 and S4:

  • Refclass objects use message-passing OO
  • Refclass objects are mutable: the usual R copy on modify semantics do not apply.

These properties makes this object system behave much more like Java and C#. read more here:

  1. http://adv-r.had.co.nz/R5.html

  2. http://www.inside-r.org/r-doc/methods/ReferenceClasses

like image 162
Mahdi Jadaliha Avatar answered Mar 01 '23 17:03

Mahdi Jadaliha


I asked this question on the R-list myself, and found a work-around to simulate a pass by reference, something in the style of :

eval(
  eval(
     substitute(
        expression(object@slot <<- value)
     ,env=parent.frame(1) )
  )
)

Far from the cleanest code around I'd say...

A suggestion coming from the R-help list, uses an environment to deal with these cases. EDIT : tweaked code inserted.

setClass("MyClass", representation(.cache='environment',masterlist="list"))

setMethod("initialize", "MyClass",
  function(.Object, .cache=new.env()) {
    .Object@masterlist <- list()
    callNextMethod(.Object, .cache=.cache)
  })

sv <- function(object,name,value) {} #store value

setMethod("sv",signature=c("MyClass","character","vector"),
  function(object, name, value) {
    [email protected]$masterlist[[name]] <- value
  })

rv <- function(object,name) {} #retrieve value

setMethod("rv",signature=c("MyClass","character"),
  function(object, name) {
    return([email protected]$masterlist[[name]])
  })
like image 45
Joris Meys Avatar answered Mar 01 '23 16:03

Joris Meys