[Rd] By default, `names<-` alters S4 objects

Hervé Pagès hpages at fhcrc.org
Mon May 16 00:02:26 CEST 2011


On 11-05-15 11:33 AM, John Chambers wrote:
> This is basically a case of a user error that is not being caught:

Sure!

   https://stat.ethz.ch/pipermail/r-devel/2009-March/052386.html

>
> On 5/14/11 3:47 PM, Hervé Pagès wrote:
>> Hi,
>>
>> I was stumped by this. The two S4 objects below looked exactly the same:
>>
>> > a1
>> An object of class "A"
>> Slot "aa":
>> integer(0)
>> > a2
>> An object of class "A"
>> Slot "aa":
>> integer(0)
>>
>> > str(a1)
>> Formal class 'A' [package ".GlobalEnv"] with 1 slots
>> ..@ aa: int(0)
>> > str(a2)
>> Formal class 'A' [package ".GlobalEnv"] with 1 slots
>> ..@ aa: int(0)
>>
>> But they were not identical:
>>
>> > identical(a1,a2)
>> [1] FALSE
>>
>> Then I found that one had a "names" attribute but not the other:
>>
>> > names(attributes(a1))
>> [1] "aa" "class" "names"
>> > names(attributes(a2))
>> [1] "aa" "class"
>>
>> > names(a1)
>> NULL
>> > names(a2)
>> NULL
>>
>> Which explained why they were not reported as identical.
>>
>> After tracking the history of 'a1', I found that it was created with
>> something like:
>>
>> > setClass("A", representation(aa="integer"))
>> [1] "A"
>> > a1 <- new("A")
>> > names(a1) <- "K"
>> > names(a1)
>> NULL
>>
>> So it seems that, by default (i.e. in the absence of a specialized
>> method), the `names<-` primitive is adding a "names" attribute to the
>> object. Could this behaviour be modified so it doesn't alter the object?
>
> Eh? But you did alter the object. Not only that, you altered it in what
> is technically an invalid way: Adding a names attribute to a class that
> has no names slot.

Ah, that's interesting. I didn't know I could put a names slot in my
class. Last time I tried was at least 3 years ago and that was causing
problems (don't remember the exact details) so I ended up using NAMES
instead. Trying again with R-2.14:

   > setClass("A", representation(names="character"))

   > a <- new("A")

   > attributes(a)
   $names
   character(0)

   $class
   [1] "A"
   attr(,"package")
   [1] ".GlobalEnv"

   > names(a)
   NULL

   > names(a) <- "K"

   > attributes(a)
   $names
   [1] "K"

   $class
   [1] "A"
   attr(,"package")
   [1] ".GlobalEnv"

   > names(a)
   NULL

Surprise! But that's another story...

>
> The modification that would make sense would be to give you an error in
> the above code. Not a bad idea, but it's likely to generate more
> complaints in other contexts, particularly where people don't
> distinguish the "list" class from lists with names (the "namedList" class).
>
> A plausible strategy:
> 1. If the class has a vector data slot and no names slot, assign the
> names but with a warning.
>
> 2. Otherwise, throw an error.
>
> (I.e., I would prefer an error throughout, but discretion ....)

Or, at a minimum (if no consensus can be reached about the above
strategy), not add a "names" attribute set to NULL. My original
post was more about keeping the internal representation of objects
"normalized", in general, so identical() is more likely to be
meaningful.

Thanks,
H.

>
> Comments?
>
> John
>
>
>>
>> Thanks,
>> H.
>>
>>
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel


-- 
Hervé Pagès

Program in Computational Biology
Division of Public Health Sciences
Fred Hutchinson Cancer Research Center
1100 Fairview Ave. N, M1-B514
P.O. Box 19024
Seattle, WA 98109-1024

E-mail: hpages at fhcrc.org
Phone:  (206) 667-5791
Fax:    (206) 667-1319



More information about the R-devel mailing list