S4 pass-by-value work-around?
Hi again Jeff... Jeffrey Spies <jspies2008 at gmail.com> writes:
Thanks for the response, Martin. While the solutions offered update the object appropriately, we wouldn't get the desired return value (a string followed by the counter, "unique_1") when the methods are called. Do you know a way of dealing with this?
I don't have a solution for you, other than calling a method to
increment the counter and a second to retrieve the current name.
Here's another unsatisfactory solution...
setClass("Stateful",
representation=representation(
state="environment"))
setMethod("initialize", "Stateful",
function(.Object, ..., state=new.env(parent=emptyenv())) {
state[["count"]] <- 0
callNextMethod(.Object, ..., state=state)
})
setGeneric("state", function(x) standardGeneric("state"))
setMethod("state", "Stateful", function(x) x at state)
setGeneric("uname", function(x, ...) standardGeneric("uname"))
setMethod("uname", "Stateful", function(x, ...) {
state <- state(x)
assign("count", state[["count"]] + 1, state)
paste("unique", state[["count"]], sep="_")
})
s <- new("Stateful")
uname(s)
[1] "unique_1"
uname(s)
[1] "unique_2" ... and the reason why this will be surprising to users
s <- t <- new("Stateful")
uname(s)
[1] "unique_1"
uname(s)
[1] "unique_2"
uname(t) # hey, this is the first time I referenced t!
[1] "unique_3" I guess this points to maybe some subtle issues with what you're trying to do, arising from a tension between pass-by-value and pass-by-reference (or to my own fuzzy-headed thinking). For instance, supppose you've implemented your 'uniqueName' function to update the object but return the unique name, and you've done it without using an environment like above, so that each instance of MyMatrix has its own counter. Say you have an instance x of 'MyMatrix' in the global environment. You pass it to a function. R's pass-by-value means it gets copied to a local variable in the function, say x1. The function queries 'uniqueName', modifying x1. But x in the global environment is unchanged. So the next time this function is invoked, it gets the same 'unique' name. Is this what you were expecting? These are just my two cents, of course, maybe others have different ideas. Martin
Jeff. Martin Morgan wrote:
Hi Jeff --
two different scenarios are to overwrite the current object, along the
lines of
y <- uniquify(y)
where uniquify is a method like createUniqueName but returns the
(modified) instance rather than unique name
setMethod('uniquify', 'MyMatrix', function(x) {
x at uniqueCount <- # something unique
x
})
The second is a replacement method, along the lines of
setGeneric("uniqueCount<-",
function(x, ..., value) standardGeneric("uniqueCount<-"))
setReplaceMethod("uniqueCount",
signature=c(x="MyMatrix", value="numeric"),
function(x, ..., value) {
x at uniqueCount <- value
x
})
uniqueCount(x) <- uniqueCount(x) + 1
x # now modified
This is untested psuedo-code, so I hope it's right enough to get you
going.
Martin
Jeffrey Spies <jspies2008 at gmail.com> writes:
Howdy all,
I have a problem that I'd like some advice/help in solving---it has to do
with R's pass-by-value system. I understand the issue, but am wondering
if
anyone has found a working solution in dealing with it for cases when one
wants to modify an object inside of a method, specifically when working
with
S4. I'm aware that R.oo is able to deal with this using S3, but I'd
really
rather stick to S4.
The basics of what I would like to do are coded below:
setClass("MyMatrix",
representation(
parameters="matrix",
uniqueCount="numeric"
),
prototype(
parameters=matrix(numeric(0),0,0),
uniqueCount=1
)
)
setGeneric("createUniqueName", function(object)
standardGeneric("createUniqueName"))
setMethod("createUniqueName", "MyMatrix", function(object){
retval <- paste("unique_", object at uniqueCount, sep="")
object at uniqueCount <- object at uniqueCount + 1
return(retval)
})
x <- new("MyMatrix", parameters=matrix(0, 2, 2))
createUniqueName(x) # returns "unique_1"
x # x at uniqueCount is still 1
I understand why this is happening, but am wondering how people in the
community have dealt with it, specifically when using S4. Any advice
would
be appreciated. Also, I am aware that this is somewhat of a silly
example,
but it should allow you to see what I'm trying to accomplish.
Thank you,
Jeff.
-- View this message in context: http://www.nabble.com/S4-pass-by-value-work-around--tp17997553p18012246.html Sent from the R help mailing list archive at Nabble.com.
______________________________________________ R-help at 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.
Martin Morgan Computational Biology / Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109 Location: Arnold Building M2 B169 Phone: (206) 667-2793