From mtmorgan at fhcrc.org  Mon Jun  9 00:54:53 2008
From: mtmorgan at fhcrc.org (Martin Morgan)
Date: Sun, 08 Jun 2008 15:54:53 -0700
Subject: [Rd] slot(obj, "nosuch") documentation question
In-Reply-To: <484C402D.1030408@r-project.org> (John Chambers's message of
	"Sun, 08 Jun 2008 16:25:17 -0400")
References: <Pine.OSF.4.58.0806070258001.292185@wotan.mdacc.tmc.edu>
	<484C402D.1030408@r-project.org>
Message-ID: <6ph63sj7d1e.fsf@lamprey.fhcrc.org>

John Chambers <jmc at r-project.org> writes:

> Paul Roebuck wrote:
>> Using slot() on object (or "@") and using a nonexistent
>> slotname returns an error (see example code).

[snip]

>> This is in reference to writing method that might be
>> passed an object created by previous version of software,
>> and new slots were added to class in later revisions.
>>
>> For such situations, is the norm then to do
>> "slotNames(obj) %in% <slotname>" prior to accessing any
>> slotname from extended class?
>>   
> Dangerous practice.  I presume what happens is that objects are saved,
> then restored after the class has been redefined.  Restoring the old
> object creates an invalid object of the class.  You really should
> follow the restore by "fixing" any out of date objects.
>
> It would be nice if R had versioning software that did some of this
> automatically, although in general it's a tough problem.
>
> Perhaps other users who have encountered the problem of revising
> classes might comment on what their practice is.  Managing changing
> class definitions is an interesting and important topic.

The not completely satisfactory solution in the Bioconductor package
Biobase is classes Versioned (a 'mix-in' class to provide versioning
information and dispatch) and Versions (to represent version strings),
plus generics isVersioned, isCurrent, classVersion, classVersion<- for
accessing Versioned, and updateObject for providing a common interface
to the update operation.

Versioned is a class with slot .__classVersion__ that the developer
populates with a vector of Version objects. isCurrent is meant to be
the main entry point for assessing version, and compares the class
version of the object with the class version recorded in the class
definition. It also grandfathers in instances that existed before
Versioned itself was added to the class by checking that the object
has its S4 bit set, and that the instance is actually versioned. The
developer is expected to write updateObject methods that know how to
update from previous versions to the current version, and
callNextMethod to delegate responsibility to inherited methods
(including a default that tries to create a new instance by copying
slots from the current object into a newly created instance).

There are several complexities. isCurrent has to make decisions about
the current-ness of slot content (much as validObject
does). Inheritance means that only a portion of the class hierarchy
might be out-of-date so length(Versions) > 1 is the norm. Methods are
not associated with classes, so in a sense and for reproducibility
'isCurrent' might mean that the object was created with the same
version of R and relevant packages as are currently in
use. updateObject would really like to have a semantic and method
dispatch like validObject, where each updateObject method takes
responsibility for updating only the portion of the class that the
method is responsible for.

There are a number of aspects that are unsatisfactory about the
implementation. The developer has to manage class version numbering
(there's no hashing, say, of the class definition to automatically
register a new class; hashing is more complicated than at first sight
because components of the class can be out of date), including an
awkward way of capturing versions of inherited classes. Out-of-date
objects are not detected when loaded, but typically when a method
fails (and then the user writes to the bioc mailing list and is told
to use updateObject; key methods in Biobase check for class version,
but this is too expensive for every operation and many packages
outside Biobase make use of Biobase classes without checking version
information). Writing updateObject methods is challenging, in part
because updateObject uses 'standardGeneric' for dispatch and the
developer has to manage both updating the object and dispatching to
appropriate 'next' methods.

>From the user perspective, updateObject seems to have been quite
successful -- it provides a clean way for the user to solve a problem,
once it's been diagnosed.

Improvements on an iteration of this might (a) develop a default
updateObject method that 'did the right thing' more reliably, much as
'initialize,ANY-method' does. In fact, the current
updateObject,ANY-method does seem to be moderately successful at
this. (b) generalize the 'validObject' dispatch model and use that to
more clearly delineate the responsibilities of updateObject methods
(which currently have to be update their part of the object and
dispatch to the 'next' method and slots, if appropriate). (c) check
object version on load, which would require a change to R itself, or
some unique discipline on the part of objects from the package.

Martin

> John
>>
>> TIA
>>
>>
>> R version 2.7.0 Patched (2008-06-04 r45830)
>>
>> ----------------------------------------------------------
>> SIGSIG -- signature too long (core dumped)
>>
>> ______________________________________________
>> R-devel at r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>
>>
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel

-- 
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



[Rd] slot(obj, "nosuch") documentation question
Martin Morgan