1

Referring to this example:

z <- list(a = 1, b = "c", c = 1:3)  
names(z)  
# change just the name of the third element.  
names(z)[3] <- "c2"  
z  

The names documentation says "see the examples. This works because the expression there is evaluated as z <- "names<-"(z, "[<-"(names(z), 3, "c2"))."

What is this final line of code about? It matches no R syntax that I'm familiar with, so I can't even fathom how to read it. If anything, it seems more complex than the example that it's trying to explain. How do I read it?

J. Mini
  • 1,632
  • 5
  • 29

1 Answers1

3

That part of the documentation is indeed badly written, I don't blame you for being confused.

Here is the short answer, say you have a vector z = c(a = 1, b = 2, c = 3), then the following are equivalent:

names(z)[3] <- "c2"

and

z <- "names<-"(z, "[<-"(names(z), 3, "c2"))

That's all the documentation is saying.

Here's the longer answer: in R you are probably familiar with the basic syntax of a function, so let's say you have foo = function(x,y) x + y then you are probably used to calling foo(1, 2). You may also have seen 'infix' operators such as +, so you're probably familiar with 1 + 2. However internally this is actually read as "+"(1,2) (try this it will work). A similar thing is seen with assignment and extraction functions, like x[1] (for some vector x) or as in this example names(z)[3] <- where <- is the assignment operator.

To make this example even more complicated there's actually two separate infix operators being used! There's names<- and there's [<-, the first one is used to set the name of a vector and the second one is used to set a value in a vector after having first extracted the vector (I know there's a lot going on here).

So breaking down what that line is telling in more familiar R code:

z <- "names<-"(z, "[<-"(names(z), 3, "c2"))
  1. z: Original vector
  2. y = names(z): Character vector - names of z.
  3. y[3]<-"c2": Extract the third element of y and assign it value "c2". Now we are at "[<-"(names(z), 3, "c2").
  4. names(z)<-y: Set the names of z as y. Now we are at "names<-"(z, "[<-"(names(z), 3, "c2")).

Just to make things even more confusing "names<-" doesn't save the newly named vector, it just sets the new names. Which is why z <- "names<-"... is required at the end to overwrite the original variable with the newly named one.

And showing this with R code:

> z = c(a = 1, b = 2, c = 3)
> print(z)
a b c 
1 2 3 
> names = names(z)
> names[3] = "c2"
> names(z) = names
> print(z)
 a  b c2 
 1  2  3 
RaphaelS
  • 754
  • 2
  • 14