[R] Change value of a slot of an S4 object within a method.

Steve Lianoglou mailinglist.honeypot at gmail.com
Wed Aug 25 18:21:46 CEST 2010


Hi Joris,

On Wed, Aug 25, 2010 at 11:56 AM, Joris Meys <jorismeys at gmail.com> wrote:
> Dear all,
>
> I have an S4 class with a slot "extra" which is a list. I want to be
> able to add an element called "name" to that list, containing the
> object "value" (which can be a vector, a dataframe or another S4
> object)
>
> Obviously
>
> setMethod("add.extra",signature=c("PM10Data","character","vector"),
>  function(object,name,value){
>             object at extra[[name]] <- value
>  }
> )
>
> Contrary to what I would expect, the line :
> eval(eval(substitute(expression(object at extra[[name]] <<- value))))
>
> gives the error :
> Error in object at extra[[name]] <<- value : object 'object' not found
>
> Substitute apparently doesn't work any more in S4 methods...
>
>  I found a work-around by calling the initializer every time, but this
> influences the performance. Returning the object is also not an
> option, as I'd have to remember to assign that one each time to the
> original name.
>
> Basically I'm trying to do some call by reference with S4, but don't
> see how I should do that. How would I be able to tackle this problem
> in an efficient and elegant way?

In lots of my own S4 classes I define a slot called ".cache" which is
an environment for this exact purpose.

Using this solution for your scenario might look something like this:

setMethod("add.extra",signature=c("PM10Data","character","vector"),
function(object, name, value) {
  object at .cache$extra[[name]] <- value
})

I'm not sure what your entire problem looks like, but to "get" your
extra list, or a value form it, you could:

setMethod("extra", signature="PM10Data",
function(object, name=NULL) {
  if (!is.null(name)) {
    object at .cache$extra[[name]]
  } else {
    object at .cache$extra
})

... or something like that.

The last thing you have to be careful of is that you nave to make sure
that each new("PM10Data") object you have initializes its *own* cache:

setClass("PM10Data", representation(..., .cache='environment'))
setMethod("initialize", "PM10Data",
function(.Object, ..., .cache=new.env()) {
  callNextMethod(.Object, .cache=.cache, ...)
})

Does that make sense?

-- 
Steve Lianoglou
Graduate Student: Computational Systems Biology
 | Memorial Sloan-Kettering Cancer Center
 | Weill Medical College of Cornell University
Contact Info: http://cbio.mskcc.org/~lianos/contact



More information about the R-help mailing list