From maechler at stat.math.ethz.ch  Thu Nov 16 10:07:51 2006
From: maechler at stat.math.ethz.ch (Martin Maechler)
Date: Thu, 16 Nov 2006 10:07:51 +0100
Subject: [Rd] valid objects -> using S4 {was "Re:  c.factor"}
In-Reply-To: <Pine.LNX.4.44.0611151916171.17215-100000@reclus.nhh.no>
References: <455B523B.4050800@lancaster.ac.uk>
	<Pine.LNX.4.44.0611151916171.17215-100000@reclus.nhh.no>
Message-ID: <17756.10855.57634.676687@stat.math.ethz.ch>

>>>>> "Roger" == Roger Bivand <Roger.Bivand at nhh.no>
>>>>>     on Wed, 15 Nov 2006 19:27:11 +0100 (CET) writes:

    Roger> On Wed, 15 Nov 2006, "BaRow" == Barry Rowlingson wrote:


      > BillD> It does not remove names in Splus either, just all
      > BillD> other attributes.  I see c() used in several Splus
      > BillD> functions as a way to convert a matrix into a vector
      > BillD> (by removing the .Dims and .Dimnames attributes).
      >> 
      BaRow> I dont see the logic in certain attribute names
      BaRow> (?attr lists 'class', 'comment', 'dim', 'dimnames',
      BaRow> 'names', 'row.names' and 'tsp') being 'special'. Why
      BaRow> are matrices vectors with some 'magic' attribute
      BaRow> 'dim', and possibly some non-magic attributes like
      BaRow> 'umbongo' and 'fnord'? I'd have the dim (and other
      BaRow> essential properties of data structures) more tightly
      BaRow> bound to the data. attr(M,'dim')=NULL seems a very
      BaRow> odd way of turning a matrix into a vector.
      BaRow> 
      BaRow> If I was the R bdfl[1] I'd deprecate using 'attr' to
      BaRow> access these aspects of data objects and insist on
      BaRow> using "dim(M)" or "row.names(M)=foo".

    Roger> I have a less than vague feeling that you as bdfl are
    Roger> describing new-style classes:

indeed, thank you, Roger!

    Roger> library(Matrix)
    Roger> x <- Matrix(1:6, nrow=2, ncol=3)
    Roger> getSlots(class(x))
    Roger> slot(x, "Dim")
    Roger> slot(x, "Dim") <- NULL

which gives

Error in checkSlotAssignment(object, name, value) : 
	assignment of an object of class "NULL" is not valid for slot "Dim" in an object of class "dgeMatrix"; is(value, "integer") is not TRUE

    Roger> but perhaps unfortunately:

    Roger> slot(x, "Dim") <- as.integer(c(0,0,0))

    Roger> works! Maybe not quite what was intended?

Indeed it does not signal an error,  surprisingly to you and others.
Note however that subsequently

 > validObject(x)
 Error in validObject(x) : invalid class "dgeMatrix" object: Dim slot must be of length 2

. . . . . 

This seems to have become a QFAQ (quite frequently asked question):

 Q: Why does R not signal an error when I assign invalid contents
    to a slot of an S4 object?

 A: Calling validObject() on every slot assignment would
    - inhibit building S4 objects incrementally ``until they are valid''
    - potentially lead to too slowly executing code.

Consequence:  

 Only ``low-level'' programming should use
   slot(A, "sn") <- ....  or the equivalent
        A @ sn   <- ....
 and then the programmeR is solely responsible to construct a
 valid object -- or needs to expliclictly call validObject() at
 the end of the construction process.

 Normal construction of S4 objects should use

 - either  new("..", .....)  
   which calls validObject() 
   [unless for new("...") with no extra args]

 - or higher level constructors 
   such as you did in the example by calling Matrix().
   

John Chambers has much more to say on this, but I think most of
it has already been written in the Green Book.

--
Martin Maechler, ETH Zurich



[Rd] valid objects -> using S4 {was "Re: c.factor"}
Martin Maechler