Hi Steve, thanks for the tip. I'll definitely take a closer look at your solution for implementation for future use. But right now I don't have the time to start rewriting my class definitions.
Luckily, I found where exactly things were going wrong. After reading into the documentation about the evaluation in R, I figured out I have to specify the environment where substitute should look explicitly as parent.frame(1). I still don't understand completely why exactly, but it does the job. Thus : eval(eval(substitute(expression(obj...@extra[[name]] <<- value)))) should become : eval( eval( substitute( expression(obj...@extra[[name]] <<- value) ,env=parent.frame(1) ) ) ) Tried it out and it works. Cheers Joris On Wed, Aug 25, 2010 at 6:21 PM, Steve Lianoglou <mailinglist.honey...@gmail.com> wrote: > Hi Joris, > > On Wed, Aug 25, 2010 at 11:56 AM, Joris Meys <jorism...@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){ >> obj...@extra[[name]] <- value >> } >> ) >> >> Contrary to what I would expect, the line : >> eval(eval(substitute(expression(obj...@extra[[name]] <<- value)))) >> >> gives the error : >> Error in obj...@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) { > obj...@.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)) { > obj...@.cache$extra[[name]] > } else { > obj...@.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 > ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.