[Rd] surprising behaviour of names<-

Wacek Kusnierczyk Waclaw.Marcin.Kusnierczyk at idi.ntnu.no
Sat Mar 14 00:58:42 CET 2009


Tony Plate wrote:
> Wacek Kusnierczyk wrote:
>> Tony Plate wrote:
>>    
>>> Is there anything incorrect or missing in the help page for normal
>>> usage of the replacement function for 'names'? (i.e., when used in an
>>> expression like 'names(x) <- ...')
>>>     
>>
>> what is missing here in the first place is a specification of what
>> 'normal' means.  as far as i can see from the man page, 'normal' does
>> not exclude prefix use.  and if so, what is missing in the help page is
>> a clear statement what an application of 'names<-' will do, in the sense
>> of what a user may observe.
>>   
> Fair enough.  I looked at the help page for "names" after sending my
> email, and was surprised to see the following in the "DETAILS" section:
>
>   "It is possible to update just part of the names attribute via the
> general rules: see the examples. This works because the expression
> there is evaluated as |z <- "names<-"(z, "[<-"(names(z), 3, "c2"))|. "
>
> To me, this paragraph is far more confusing than enlightening,
> especially as also gives the impression that it's OK to use a
> replacement function in a functional form.  In my own personal opinion
> it would be a enhancement to remove that example from the
> documentation, and just say you can do things like 'names(x)[2:3] <-
> c("a","b")'.

i must say that this part of the man page does explain things to me. 
much less the code [1] berwin suggested as a piece to read and
investigate (slightly modified):

    tmp = x
    x = 'names<-'(tmp, 'foo')

berwin's conclusion seemed to be that this code
hints/suggests/fortune-tells the user that 'names<-' might be doing side
effects. 

this code illustrates what names(x) = 'foo' (the infix form) does --
that it destructively modifies x.  now, if the code were to illustrate
that the prefix form does perform side effects too, then the following
would be enough:

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

if the code were to illustrate that the prefix form, unlike the infix
form, does not perform side effects, then the following would suffice
for a discussion:

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

if the code wee to illustrate that the prefix form may or may not do
side effects depending on the situation, then it surely fails to show
that, unless the user performs some sophisticated inference which i am
not capable of, or, more likely, unless the user already knows that this
was to be shown.

without a discussion, the example is simply an unworked rubbish.  and
it's obviously wrong; it says that (slightly and irrelevantly simplified)

    names(x) = 'foo'

"is equivalent to"

    tmp = x
    x = 'names<-'(tmp, 'foo')

which is nonsense, because in the latter case you either have an
additional binding that you don't have in the former case, or, worse,
you rebind, possibly with a different value, a name that has had a
binding already.  it's a gritty-nitty detail, but so is most of
statistics based on nitty-gritty details which non-statisticians are
happy to either ignore or be ignorant about.


[1] http://stat.ethz.ch/R-manual/R-devel/doc/manual/R-lang.html#Comments

>
> I often use name replacement functions in a functional way, and
> because one can't use 'names<-' etc in this way, 

note, this 'because' does not follow in any way from the man page, or
the section of 'r language definition' referred to above.


> I define my own functions like the following:
>
> set.names <- function(n,x) {names(x) <- n; x}

it appears that

    set.names = function(n, x) 'names<-'(x, n)

would do the job (guess why).

>
> (and similarly for set.rownames(), set colnames(), etc.)
>
> I would highly recommend you do this rather than try to use a call
> like "names<-"(x, ...).

i'm almost tempted to extend your recommendation to 'define your own
function for about every function already in r' ;)

vQ



More information about the R-devel mailing list