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

John Chambers jmc at r-project.org
Mon May 16 22:53:08 CEST 2011



On 5/16/11 10:09 AM, Hervé Pagès wrote:
> On 11-05-16 09:36 AM, John Chambers wrote:
>> You set up a names slot in a non-vector. Maybe that should be allowed,
>> maybe not. But in any case I would not expect the names() primitive to
>> find it, because your object has a non-vector type ("S4").
>
> But the names<-() primitive *does* find it. So either names() and
> names<-() should both find it, or they shouldn't. I mean, if you care
> about consistency and predictability of course.

That's not the only case where borderline or mistaken behavior is caught 
on assignment, but not on access.  The argument is that assignment can 
afford to check things, but access needs to be fast.  Slot access is 
another case.  There, assignment ensures legality so access can be quick.

The catch is that there are sometimes backdoor ways to assignments, 
partly because slots, attributes and some "builtin" properties like 
names overlap.

What we were talking about before was trying to evolve a sensible rule 
for assigning names to S4 objects.  Let's try to discuss what people 
need to do before carping or indulging in sarcasm.

John

>
> H.
>
>
>> You could do
>> a at names if you thought that made sense:
>>
>>
>> > setClass("A", representation(names="character"))
>> [1] "A"
>> > a <- new("A")
>> > a at names <- "xx"
>> > a at names
>> [1] "xx"
>> > names(a)
>> NULL
>>
>>
>> If you wanted something sensible, it's more like:
>>
>> > setClass("B", representation(names = "character"), contains =
>> "integer")
>> [1] "B"
>> > b <- new("B", 1:5)
>> > names(b) <- letters[1:5]
>> > b
>> An object of class "B"
>> [1] 1 2 3 4 5
>> Slot "names":
>> [1] "a" "b" "c" "d" "e"
>>
>> > names(b)
>> [1] "a" "b" "c" "d" "e"
>>
>> This allows both the S4 and the primitive code to deal with a
>> well-defined object.
>>
>> John
>>
>>
>> On 5/15/11 3:02 PM, Hervé Pagès wrote:
>>> 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
>> ......
>>
>>>
>>> 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
>>>
>>>
>
>



More information about the R-devel mailing list