[Rd] surprising behaviour of names<-

Wacek Kusnierczyk Waclaw.Marcin.Kusnierczyk at idi.ntnu.no
Thu Mar 12 15:21:50 CET 2009


Berwin A Turlach wrote:
> On Thu, 12 Mar 2009 10:53:19 +0100
> Wacek Kusnierczyk <Waclaw.Marcin.Kusnierczyk at idi.ntnu.no> wrote:
>
>   
>> 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.
>>     
>
> But since R supposedly 

*supposedly*

> uses call-by-value (though we know how to
> circumvent that, don't we?) 

we know how a lot of built-ins hack around this, don't we, and we also
know that call-by-value is not really the argument passing mechanism in r.

> wouldn't you always expect that a copy of
> the object is returned?
>   

indeed!  that's what i have said previously, no?  there is still space
for the smart (i mean it) copy-on-assignment behaviour, but it should
not be visible to the user, in particular, not in that 'names<-'
destructively modifies the object it is given when the refcount is 1. 
in my humble opinion, there is either a design flaw or a bug here.


>  
>   
>>> 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?  
>>     
>
> This seems to suggest 

seems to suggest?  is not the purpose of documentation to clearly,
ideally beyond any doubt, specify what is to be specified?

> that in this case the infix and prefix syntax
> is not equivalent as it does not say that 
>   

are you suggesting fortune telling from what the docs do *not* say?

> 	names(x) <- c("a","b")
> is equivalent to
> 	x <- "names<-"(x, value=c("a","b"))
> and I was commenting on the claim that the infix syntax is equivalent
> to the prefix syntax.
>
>   
>> does this say anything about what 'names<-'(...) actually
>> returns?  updated *tmp*, or a copy of it?
>>     
>
> Since R uses pass-by-value, 

since?  it doesn't!

> you would expect the latter, wouldn't
> you?  

yes, that's what i'd expect in a functional language.

> If you entertain the idea that 'names<-' updates *tmp* and
> returns the updated *tmp*, then you believe that 'names<-' behaves in a
> non-standard way and should take appropriate care.
>   

i got lost in your argumentation.  i have given examples of where
'names<-' destructively modifies and returns the updated object, not a
copy.  what is your point here?

> And the fact that a variable *tmp* is used hints to the fact that
> 'names<-' might have side-effect.  

are you suggesting fortune telling from the fact that a variable *tmp*
is used?


> If 'names<-' has side effects,
> then it might not be well defined with what value x ends up with if
> one executes:
> 	x <- 'names<-'(x, value=c("a","b"))  
>   

not really, unless you mean the returned object in the referential sense
(memory location) versus value conceptually.  here x will obviously have
the value of the original x plus the names, *but* indeed you cannot tell
from this snippet whether after the assignment x will be the same,
though updated, object or will rather be an updated copy:

    x = c(1)
    x = 'names<-'(x, 'foo')
    # x is the same object

    x = c(1)
    y = x
    x = 'names<-'(x, 'foo')
    # x is another object

so, as you say, it is not well defined with what object will x end up as
its value, though the value of the object visible to the user is well
defined.  rewrite the above and play:

    x = c(1)
    y = 'names<-'(x, 'foo')
    names(x)

what are the names of x?  is y identical (sensu refernce) with x, is y
different (sensu reference) but indiscernible (sensu value) from x, or
is y different (sensu value) from x in that y has names and x doesn't?



> This is similar to the discussion what value i should have in the
> following C snippet:
> 	i = 0;
>  	i += i++;
>   

nonsense, it's a *completely* different issue.  here you touch the issue
of the order of evaluation, and not of whether an object is copied or
modified;  above, the inverse is true.

in fact, your example is useless because the result here is clearly
specified by the semantics (as far as i know -- prove me wrong).  you
lookup i (0) and i (0) (the order does not matter here), add these
values (0), assign to i (0), and increase i (1). 

i have a better example for you:

    int i = 0;
    i += ++i - ++i

which will give different final values for i in c (2 with gcc 4.2, 1
with gcc 3.4), c# and java (-1), perl (2) and php (1).  again, this has
nothing to do with the above.



>  
> [..]
>   
>>> 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. 
>>     
>
> I guess that would require a rewrite (or extension) of the parser.  To
> me, Section 10.1.2 of the Language Definition manual suggests that once
> an expression is parsed, you cannot distinguish any more whether
> 'names<-' was called using infix syntax or prefix syntax.
>   

but this must be nonsense, since:

    x = 1
    'names<-'(x, 'foo')
    names(x)
    # NULL

    x = 1
    names(x) <- 'foo'
    names(x)
    # "foo"

clearly, there is not only syntactic difference here.  but it might be
that 10.1.2 does not suggest anything like what you say.


> Thus, I guess you want to start a discussion with R Core whether it is
> worthwhile to change the parser such that it keeps track on whether a
> function was used with infix notation or prefix notation and to
> provide for most (all?) assignment operators implementations that use
> destructive semantics if the infix version was used and always copy if
> the prefix notation is used. 
>   

as i explained a few months ago, i study r to find examples of bad
design.  if anyone in the r core is interested in having the problems i
report fixed, i'm happy to get involved in a discussion about the design
and implementation.  if not, i'm happy with just pointing out the issues.

cheers,
vQ



More information about the R-devel mailing list