Gabor Grothendieck wrote: > On Fri, Jul 9, 2010 at 5:09 AM, Peter Dalgaard <pda...@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"
Or, to minimize it further: > x <- structure(1, class="y") > is.object(x) [1] TRUE > is.object(x*1) [1] TRUE > is.object(1*x) [1] FALSE > class(x*1) [1] "y" > class(1*x) [1] "y" Yup, that looks like a bug. -- Peter Dalgaard Center for Statistics, Copenhagen Business School Phone: (+45)38153501 Email: pd....@cbs.dk Priv: pda...@gmail.com ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel