Simon Zehnder
2013-Mar-01 14:13 UTC
[R] S4-classes: Assignment of values to slots by reference
Dear R-users, I am working on a project that uses S4-classes. At some point I encountered the problem - well known to R - that I have to pass 3 different objects to a function, that should modify several slots of them and of course there is no passing by reference in R. Then I read this thread by Steve Lianoglou: https://stat.ethz.ch/pipermail/r-help/2010-August/250468.html, which offers from viewpoint of OOP an elegant solution. But I do not use an Object Method, but a regular function, pass in several objects and modify them. Here is an example with 1 Object using Steve's approach: setClass("example", representation( par = "matrix", .cache = "environment") ) setMethod("initialize", "example", function(.Object, ..., .cache = new.env()) { callNextMethod(.Object, .cache = .cache, ...) } ) ex <- new("example", par = matrix()) fmodify <- function(O1) { pm <- mean(rnorm(100)) pm <- matrix(pm) O1 at .cache$par <- pm } fmodify(ex) So far so good. Everything worked nicely. But of course the value computed in the function 'fmodify' is now in the slot ex at .cache$par: ex at .cache$par and not in ex at par. Is there a possibility to get it into ex at par? Best Simon
Martin Morgan
2013-Mar-01 18:14 UTC
[R] S4-classes: Assignment of values to slots by reference
On 03/01/2013 06:13 AM, Simon Zehnder wrote:> Dear R-users, > > I am working on a project that uses S4-classes. At some point I encountered the problem - well known to R - that I have to pass 3 different objects to a function, that should modify several slots of them and of course there is no passing by reference in R.Hi Simon -- for this problem it is helpful to recognize that the default 'initialize' method is actually a copy constructor, so .A = setClass("A", representation(x="numeric", y="numeric", z="numeric")) a = .A(x=1:5) initialize(a, y=1:2, z=2:1) # update y, z > initialize(a, y=1:2, z=2:1) An object of class "A" Slot "x": [1] 1 2 3 4 5 Slot "y": [1] 1 2 Slot "z": [1] 2 1 Write your own initialize methods to obey this contract by (a) not writing an initialize method (there is none for "A", above)! or (b) using named arguments with default values taken from .Object and specified after the ..., e.g., setMethod(initialize, "A", function(.Object, ..., y=.Object at y, z=.Object at z) { ## some additional initialization, e.g., y <- abs(y) callNextMethod(.Object, ..., y=y, z=z) })> Then I read this thread by Steve Lianoglou: https://stat.ethz.ch/pipermail/r-help/2010-August/250468.html, which offers from viewpoint of OOP an elegant solution. But I do not use an Object Method, but a regular function, pass in several objects and modify them. >The thread was written before 'reference classes' were introduced; see ?ReferenceClasses for this style of programming. Hope that helps, Martin> Here is an example with 1 Object using Steve's approach: > > setClass("example", > representation( > par = "matrix", > .cache = "environment") > ) > setMethod("initialize", "example", function(.Object, ..., .cache = new.env()) { > callNextMethod(.Object, .cache = .cache, ...) > } > ) > > ex <- new("example", par = matrix()) > > fmodify <- function(O1) { > pm <- mean(rnorm(100)) > pm <- matrix(pm) > O1 at .cache$par <- pm > } > > fmodify(ex) > > > So far so good. Everything worked nicely. But of course the value computed in the function 'fmodify' is now in the slot ex at .cache$par: > > ex at .cache$par > > and not in ex at par. Is there a possibility to get it into ex at par? > > Best > > Simon > > ______________________________________________ > 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. >-- Computational Biology / Fred Hutchinson Cancer Research Center 1100 Fairview Ave. N. PO Box 19024 Seattle, WA 98109 Location: Arnold Building M1 B861 Phone: (206) 667-2793