[Rd] infinite recursion when printing former S4 objects
John Chambers
jmc at r-project.org
Sun Apr 22 00:08:14 CEST 2007
Classes that contain "matrix" are trouble. Matrix objects are, well,
weird. They look like they should be S3 classes but the object bit is
not turned on and they have no class attribute. They seem to be
recognized by much internal code on the basis of the "dim" attribute, so
they appear to dispatch S3 methods, for example.
They've been allowed as a data part in S4 class definitions, but it
seems that we should perhaps retract that, unless it can be made to work
reliably, which may not be possible without changing the semantics of
matrix objects.
The problems with class "Foo" are not just with printing. For example:
> setClass("Foo", representation(name="character"), contains="matrix")
[1] "Foo"
> x = new("Foo", 1:12)
Error: evaluation nested too deeply: infinite recursion /
options(expressions=)?
A little investigation pins this one down to as(x, "vector") <-
Aside from these really nasty features, there is a problem with
containing S3 classes in general, because the S3 dispatch can't
recognize the new class as inheriting from the S3 class. For example:
> bar = function(x)UseMethod("bar")
> bar.matrix = function(x)"Matrix bar"
> mm = matrix(1:12,3,4)
> bar(mm)
[1] "Matrix bar"
> mF = new("Foo", mm)
> bar(mF)
Error in bar(mF) : no applicable method for "bar"
> is.matrix(mF)
[1] TRUE
I do agree that the S4 bit should be turned off when an object drops
down to having no class--it's something that doesn't seem to cause the
same problems with inheritance from other basic data classes, though:
> setClass("c2", representation(name = "character"), contains = "numeric")
[1] "c2"
> cc = new("c2", 1:12)
> as(cc, "numeric")
[1] 1 2 3 4 5 6 7 8 9 10 11 12
> cn = as(cc,"numeric")
> class(cn)
[1] "integer"
> attr(cn, "class")
NULL
> isS4(cn)
[1] TRUE
> print(cn)
[1] 1 2 3 4 5 6 7 8 9 10 11 12
John
Seth Falcon wrote:
> Hello all,
>
> An S4 class that contains matrix can be converted into a matrix using
> as(). When the resulting object is printed implicitly at the command
> line, all is well. When print() is explicitly called, I see an
> infinite recursion.
>
> Here is an example:
>
> ## create a subclass of matrix
> > setClass("Foo", representation(name="character"), contains="matrix")
> [1] "Foo"
>
> ## test it out
> > f <- new("Foo", name="Sam", matrix())
> > z <- as(f, "matrix")
> > z
> [,1]
> [1,] NA
> > print(z)
> Error: evaluation nested too deeply: infinite recursion / options(expressions=)?
>
> An easy cut/paste version is below. I'm seeing this with an R 2.5.0
> beta. I noticed that isS4(z) returns TRUE. This may or may not be
> surprising, but seems quite related to the issue at hand.
>
>
> + seth
>
>
>
> ## ----------------8<--------------8<-----------------------
>
> setClass("Foo", representation(name="character"), contains="matrix")
> f <- new("Foo", name="Sam", matrix())
> f
> m <- as(f, "matrix")
> m
> print(m)
>
> ## ----------------8<--------------8<-----------------------
>
>
>
More information about the R-devel
mailing list