On Jul 9, 2010, at 12:41 PM, Deepayan Sarkar wrote: > On Fri, Jul 9, 2010 at 5:25 AM, Peter Dalgaard <pda...@gmail.com> wrote: >> 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. > > I recently came across the following surprising behaviour which turns > out to be the same issue. I had been meaning to ask for an > explanation. > >> x <- 1:20 >> class(x) > [1] "integer" >> is.object(x) > [1] FALSE >> print.integer <- function(x) print(x %% 5) >> print(x) > [1] 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 0 >> x > [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 >
... that is an entirely different issue. x is still not an object because it doesn't have any explicit S3 class so it has nothing in common with the case discussed. This is about P in REPL which uses PrintValueEnv which is turn dispatches to print() only for objects (see main and print). Cheers, Simon ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel