From ross at biostat.ucsf.edu  Tue Jun 30 22:57:44 2009
From: ross at biostat.ucsf.edu (Ross Boylan)
Date: Tue, 30 Jun 2009 13:57:44 -0700
Subject: [Rd] S4 class redefinition
In-Reply-To: <1246391912.26310.315.camel@corn.betterworld.us>
References: <1246391912.26310.315.camel@corn.betterworld.us>
Message-ID: <1246395464.26310.342.camel@corn.betterworld.us>

On Tue, 2009-06-30 at 12:58 -0700, Ross Boylan wrote:
> I haven't found much on S4 class redefinition; the little I've seen
> indicates the following is to be expected:
> 1. setClass("foo", ....)
> 2. create objects of class foo.
> 3. execute the same setClass("foo", ...) again (source the same file).
> 4. objects from step 2 are now NULL.
I'm sorry; step 4 is completely wrong.  The objects seem to be
preserved.  Some slightly modified questions remain.

Is it safe to reexecute identical code for setClass or setMethod when
you have existing objects of the class around?

Is there any protection, such as checking for existing definitions, that
is recommended before executing setClass or setMethod?

If you want to change a class or method, and have existing objects, how
do you do that?

Can scoping rules lead to situations in which some functions or methods
end up with references to the older version of the methods?  One example
is relevant to class constructors, and shows they can:

Here's a little test
> trivial <- function() 3  # stand in for a class constructor
> maker <- function(c=trivial)
+   function(x) x+c()
> oldf <- maker()
> oldf(4)
[1] 7
> trivial <- function() 20
> oldf(4)
[1] 7
> newf <- maker()
> newf(8)
[1] 28

So the old definition is frozen in the inner function, for which it was
captured by lexical scope.  Although definition of maker is not redone
after trivial is redefined, maker's default argument does get the new
value of trivial.  

Methods add another layer.  I'm hoping those with a deeper understanding
than mine can clarify where the danger spots are, and how to deal with
them.

Thanks.
Ross
> 
> Is that the expected behavior (I ran under R 2.7.1)?
> 
> Assuming it is, it's kind of unfortunate.  I can wrap my setClass code
> like this
> if (! isClass("foo")) setClass("foo", ....)
> to avoid this problem.  I've seen this in other code; is that the
> standard solution? 
> 
> I thought that loading a library was about the same as executing the
> code in its source files (assuming R only code).  But if this were true
> my saved objects would be nulled out each time I loaded the
> corresponding library.  That does not seem to be the case.  Can anyone
> explain that?
> 
> Do I need to put any protections around setMethod so that it doesn't run
> if the method is already defined?
> 
> At the moment I'm not changing the class defintion but am changing the
> methods, so I can simply avoid running setClass.
> 
> But if I want to change the class, most likely by adding a slot, what do
> I do?  At the moment it looks as if I'd need to make a new class name,
> define some coerce methods, and then locate and change the relevant
> instances.  Is there a better way?
> 
> Thanks.
> Ross Boylan
> 
>



[Rd] S4 class redefinition
Ross Boylan