Re: [Rd] Strange R object

From: Gabor Grothendieck <ggrothendieck_at_gmail.com>
Date: Fri, 09 Jul 2010 06:49:53 -0400

On Fri, Jul 9, 2010 at 5:09 AM, Peter Dalgaard <pdalgd_at_gmail.com> wrote:
> Gabor Grothendieck wrote:
>> I have *** attached *** an RData file containing an R object that
>> is acting strangely.
>>
>> Try this in a fresh workspace. Do not load zoo or any other package.
>> We load the object, zz2, from the attached RData file.  It is just
>> the number 1 with the class c("zooreg", "zoo").
>>
>> Now create an S3 print routine that simply prints an X when given
>> an object of class "zoo".
>>
>> If we use print on the object it produces an X but not if we just
>> enter it at the console.  Also the object is not identical to its
>> dput output.
>>
>> How can such an object exist?  What is it about the object that is
>> different from structure(1, class = c("zoo", "zooreg")) ?
>>
>
> There's a bit in the SEXP structure that is supposed to be turned on
> when an object has an S3 class. This is where implicit print looks,
> whereas explicit print looks, er, elsewhere. Notice that
>
>> is.object(zz2)
> [1] FALSE
>> class(zz2) <- class(zz2)
>> zz2
> X
>> is.object(zz2)
> [1] TRUE
>
> Whenever the same information is stored in two ways, there is a risk of
> inconsistency, so it is not too strange that you can have an ill-formed
> .Rdata file (if you save zz2 back out, after the above fixup, line 11
> changes from 526 to 782, corresponding to the bit being turned on).
>
> I don't think it is the job of load() to verify object structures, since
> there is no end to that task. Rather, we shouldn't create them in the
> first place, but you give us no clues as to how that object got made.
>

This was originally a large object in a program that uses a variety of packages and it took quite a long time just to narrow it down to the point where I had an object sufficiently small to post. Its not even clear at what point the object goes bad but your class(x) <- class(x) trick helped a lot and I have now been able to recreate it in a simple manner.

Below we create a new S3 class "X" with an Ops.X and print.X method. We then create an object x of that class which is just 1 with a class of "X". When we multiply 1*x we get the bad object. 1*x and x have the same dput output but compare as FALSE. 1*x is not printed by print.X even though it is of class "X" while x is printed by print.X .  If we assign 1*x to xx and use your class assignment trick (class(xx) <- class(xx)) then xx prints as expected even though it did not prior to the class assignment.

> Ops.X <- function(e1, e2) { print("Ops.X"); NextMethod(.Generic) }
> print.X <- function(x, ...) print("print.X")
> x <- structure(1, class = "X")
> dput(x)
structure(1, class = "X")
> dput(1*x)

[1] "Ops.X"
structure(1, class = "X")
> identical(x, 1*x)

[1] "Ops.X"
[1] FALSE
> 1*x

[1] "Ops.X"
[1] 1
attr(,"class")
[1] "X"
> x

[1] "print.X"
> xx <- 1*x

[1] "Ops.X"
> class(xx) <- class(xx)
> xx

[1] "print.X"



R-devel_at_r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel Received on Fri 09 Jul 2010 - 10:53:52 GMT

Archive maintained by Robert King, hosted by the discipline of statistics at the University of Newcastle, Australia.
Archive generated by hypermail 2.2.0, at Fri 09 Jul 2010 - 12:40:15 GMT.

Mailing list information is available at https://stat.ethz.ch/mailman/listinfo/r-devel. Please read the posting guide before posting to the list.

list of date sections of archive