[Rd] surprising behaviour of names<-

Wacek Kusnierczyk Waclaw.Marcin.Kusnierczyk at idi.ntnu.no
Thu Mar 12 10:53:19 CET 2009


Berwin A Turlach wrote:
>
> Whoever said that must have been at that moment not as precise as he or
> she could have been.  Also, R does not behave according to what people
> say on this list (which is good, because some times people they wrong
> things on this list) but according to how it is documented to do; at
> least that is what people on this list (and others) say. :)
>   

well, ?'names<-' says:

"
Value:
     For 'names<-', the updated object. 
"

which is only partially correct, in that the value will sometimes be an
updated *copy* of the object.

> And the R Language manual (ignoring for the moment that it is a draft
> and all that), 

since we must...

> clearly states that 
>
> 	names(x) <- c("a","b")
>
> is equivalent to
> 	
> 	'*tmp*' <- x
>          x <- "names<-"('*tmp*', value=c("a","b"))
>   

... and?  does this say anything about what 'names<-'(...) actually
returns?  updated *tmp*, or a copy of it?


> [...]
>   
>> well, i can imagine a user using the prefix 'names<-' precisely under
>> the assumption that it will perform functionally;  
>>     
>
> You mean
> 	y <- 'names<-'(x, "foo")
> instead of
> 	y <- x
> 	names(y) <- "foo"
> ?
>   

what i mean is, rather precisely, that 'names<-'(x, 'foo') will produce
a *new* object with a copy of the value of x and names as specified, and
will *not*, under any circumstances, modify x.

the first line above does not quite address this, e.g.:

    x = c(1)
    y = 'names<-'(x, 'foo')
    names(x)
    # "foo", 'should' be NULL


> Fair enough.  But I would still prefer the latter version this it is
> (for me) easier to read and to decipher the intention of the code.
>   

you're welcome to use it.  but this is personal preference, and i'm
trying to discuss the semantics of r here.  what you show is a way to
clutter the code, and you need to explicitly name the new object, while,
in functional programming, it is typical to operate on anonymous objects
passed from one function to another, e.g.

    f('names<-'(x, 'foo'))

which would have to become

    y = x
    names(y) = 'foo'
    f(y)

or

    f({y = x; names(y) = 'foo'; y})

with 'y' being a nuissance name.


>> i.e., 'names<-'(x, 'foo') will always produce a copy of x with the
>> new names, and never change the x.  
>>     
>
> I am not sure whether R ever behaved in that way, but as Peter pointed
> out, this would be quite undesirable from a memory management and
> performance point of view.  

why?  you can still use the infix names<- with destructive semantics to
avoid copying. 


> Image that every time you modify a (name)
> component of a large object a new copy of that object is created.
>   

see above.  besides, r has been several times claimed here (but see your
remark above) to be a functional language, and in this context it is
surprising that the smart (i mean it) copy-on-assignment mechanism,
which is an implementational optimization, not only becomes visible, but
also makes functions (hmm, procedures?) such as 'names<-' non-functional
-- in some, but not all, cases.

vQ



More information about the R-devel mailing list