From jmc at r-project.org  Mon Jan 10 23:10:13 2005
From: jmc at r-project.org (John Chambers)
Date: Mon Jan 10 23:10:25 2005
Subject: [Rd] S4 class no longer accepts matrix in array slot under 2.0.1
In-Reply-To: <KLEHJMEACMGEMBOOPFCAAEJPCAAA.giles.heywood@cantab.net>
References: <KLEHJMEACMGEMBOOPFCAAEJPCAAA.giles.heywood@cantab.net>
Message-ID: <41E2FD45.20404@R-project.org>

Your example and your subject heading are two different things.  If you 
meant the subject heading, that in fact works.

R> setClass("a1", representation(x="array"))
[1] "a1"
R> new("a1", x=matrix(1:12,3,4))
An object of class "a1"
Slot "x":
      [,1] [,2] [,3] [,4]
[1,]    1    4    7   10
[2,]    2    5    8   11
[3,]    3    6    9   12

That's not what your example does.  In your example, the new class 
extends "array", rather than using it as a slot.  It would have been 
clearer if you had said setClass("foo", contains="array"), but your code 
is correct for that purpose.

On first examination, I believe the problem is just what the message 
says it is.  You gave as a new object (and NOT as a slot) an object from 
a subclass of a superclass of "foo".  This is allowed, but has to be 
done by replacing the part of a "foo" object corresponding to the 
"array" contained in a "matrix" object.  Of course, we know that's 
actually the whole object, but nothing has told the software this.  And, 
indeed, it doesn't find the necessary replacement method.

Here's an example similar to what you are doing, but using actual 
classes.  Barring screwups on my part, it shows that the mechanism works 
as asserted.  Classes "c1", "c2", "c3" follow the roles of "array", 
"matrix", and "foo" in your example.
R> setClass("c1", representation(x="numeric"))
[1] "c1"
R> setClass("c2", contains="c1")
[1] "c2"
R> setClass("c3", contains = "c1")
[1] "c3"
R> x2 = new("c2", x=1)
R> x3 = new("c3", x2)
R> x3
An object of class "c3"
Slot "x":
[1] 1

Classes "matrix" and "array" are rather peculiar in R; among other 
things, they act like vector data types in that is.object() is FALSE.
And you cannot have an "array" with a dimension of length 2.

R> class(array(1:12, dim=c(3,4)))
[1] "matrix"

Also, because they don't have a consistent set of "slots" (they may or 
may not have a "dimnames), they aren't quite real classes in an S4 
sense.  It would be nice to fix this mess, but not obviously possible 
while being back compatible.

It's possible that there is a fix to get around the particular error 
here, without breaking the more general pattern--I'll take a look.

Otherwise, you may need to follow the approach of your subject heading, 
and define a new class with an array as a slot.

Giles Heywood wrote:

> I have an S4 class with a slot of class "array", and in upgrading to 2.0.1
> (from 1.9.1) I have encountered a change in behaviour. This causes me some
> difficulties if I want to allow 2-dimensional arrays in the slot.
> 
> The following (in 2.0.1) illustrates the point:
> 
> 
>>setClass("foo",representation("array"))
> 
> [1] "foo"
> 
>>a <- new("foo",array(NA,2:4))
>>b <- new("foo",matrix(NA,2,3))
> 
> Error in "as<-"(`*tmp*`, Classi, value = c(NA, NA, NA, NA, NA, NA)) :
>         No method or default for as() replacement of "foo" with
> Class="matrix"
> 
> This last error did not occur under 1.9.1.
> 
> I conclude that in this context the methods package does not recognise
> "matrix" as a subclass of "array". However if I use getClass(), I see that R
> recognises "matrix" as a subclass of "array" (and vice-versa).  So is this
> new behaviour correct?

You conclude incorrectly, as noted above.
> 
> [this is a re-posting to R-devel of a question earlier posted to R-help,
> which attracted limited response]
> 
> ______________________________________________
> R-devel@stat.math.ethz.ch mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>


[Rd] S4 class no longer accepts matrix in array slot under 2.0.1
John Chambers