[Rd] surprising behaviour of names<-

Wacek Kusnierczyk Waclaw.Marcin.Kusnierczyk at idi.ntnu.no
Tue Mar 10 18:07:30 CET 2009


Peter Dalgaard wrote:
> Wacek Kusnierczyk wrote:
>   
>> playing with 'names<-', i observed the following:
>>   
>>     x = 1
>>     names(x)
>>     # NULL
>>     'names<-'(x, 'foo')
>>     # c(foo=1)
>>     names(x)
>>     # NULL
>>
>> where 'names<-' has a functional flavour (does not change x), but:
>>
>>     x = 1:2
>>     names(x)
>>     # NULL
>>     'names<-'(x, 'foo')
>>     # c(foo=1, 2)
>>     names(x)
>>     # "foo" NA
>>   
>> where 'names<-' seems to perform a side effect on x (destructively
>> modifies x).  furthermore:
>>
>>     x = c(foo=1)
>>     names(x)
>>     # "foo"
>>     'names<-'(x, NULL)
>>     names(x)
>>     # NULL
>>     'names<-'(x, 'bar')
>>     names(x)
>>     # "bar" !!!
>>
>>     x = c(foo=1)
>>     names(x)
>>     # "foo"
>>     'names<-'(x, 'bar')
>>     names(x)
>>     # "bar" !!!
>>
>> where 'names<-' is not only able to destructively remove names from x,
>> but also destructively add or modify them (quite unlike in the first
>> example above).
>>
>> analogous code but using 'dimnames<-' on a matrix performs a side effect
>> on the matrix even if it initially does not have dimnames:
>>
>>     x = matrix(1,1,1)
>>     dimnames(x)
>>     # NULL
>>     'dimnames<-'(x, list('foo', 'bar'))
>>     dimnames(x)
>>     # list("foo", "bar")
>>
>> this is incoherent with the first example above, in that in both cases
>> the structure initially has no names or dimnames attribute, but the end
>> result is different in the two examples.
>>
>> is there something i misunderstand here?
>>     
>
> Only the ideology/pragmatism... In principle, R has call-by-value
> semantics and a function does not destructively modify its arguments(*),
> and foo(x)<-bar behaves like x <- "foo<-"(x, bar). HOWEVER, this has
> obvious performance repercussions (think x <- rnorm(1e7); x[1] <- 0), so
> we do allow destructive modification by replacement functions, PROVIDED
> that the x is not used by anything else. On the least suspicion that
> something else is using the object, a copy of x is made before the
> modification.
>
> So
>
> (A) you should not use code like y <- "foo<-"(x, bar)
>
> because
>
> (B) you cannot (easily) predict whether or not x will be modified
> destructively
>
>   

that's fine, thanks, but i must be terribly stupid as i do not see how
this explains the examples above.  where is the x used by something else
in the first example, so that 'names<-'(x, 'foo') does *not* modify x
destructively, while it does in the other cases?

i just can't see how your explanation fits the examples -- it probably
does, but i beg you show it explicitly.
thanks.

vQ



More information about the R-devel mailing list