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.
views:
89answers:
2As far as I know (and if I get you correctly), you have to recopy the whole object. You can't easily pass values by reference, it is always passed "by value". So once you have modified (a copy of) your object, you need to recopy it back to your object.
John Chamber is pretty explicit about it in his book Software for Data Analysis. It's a way to avoid surprises or side effects.
I think there are some workaround using environments, but I can't help with this.
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]])
})