15

I am wondering how assignment works in the R language.

Consider the following R shell session:

> x <- c(5, 6, 7)
> x[1] <- 10
> x
[1] 10 6 7
>

which I totally understand. The vector (5, 6, 7) is created and bound to the symbol 'x'. Later, 'x' is rebound to the new vector (10, 6, 7) because vectors are immutable data structures.

But what happens here:

> c(4, 5, 6)[1] <- 10
Error in c(4, 5, 6)[1] <- 10 :
  target of assignment expands to non-language object
>

or here:

> f <- function() c(4, 5, 6)
> f()[1] <- 10
Error in f()[1] <- 10 : invalid (NULL) left side of assignment
>

It seems to me that one can only assign values to named data structures (like 'x').

The reason why I am asking is because I try to implement the R language core and I am unsure how to deal with such assignments.

Thanks in advance

Duncan Babbage
  • 19,972
  • 4
  • 56
  • 93
Sven Hager
  • 3,144
  • 4
  • 24
  • 32
  • 2
    That's a great question. You may find a little bit of insight in some of the answers here: http://stackoverflow.com/questions/10449366/levels-what-sorcery-is-this – Ari B. Friedman May 23 '12 at 13:17

3 Answers3

16

It seems to me that one can only assign values to named data structures (like 'x').

That's precisely what the documentation for ?"<-" says:

Description:

 Assign a value to a name.

x[1] <- 10 doesn't use the same function as x <- c(5, 6, 7). The former calls [<- while the latter calls <-.

IRTFM
  • 258,963
  • 21
  • 364
  • 487
Joshua Ulrich
  • 173,410
  • 32
  • 338
  • 418
  • 1
    Ah ok. But the parser does not seem to vary between x <- 2 and x[1] <- 2 because the `canonical` function gives me `<-`(x, 2) and `<-`(`[`(x, 1), 2) So I think the interpreter dispatches somehow on the lvalue. – Sven Hager May 23 '12 at 12:53
16

As per @Owen's answer to this question, x[1] <- 10 is really doing two things. It is calling the [<- function, and it is assigning the result of that call to x.

So what you want to achieve your c(4, 5, 6)[1] <- 10 result is:

> `[<-`(c(4, 5, 6),1, 10)
[1] 10  5  6
Community
  • 1
  • 1
Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235
  • The `<-` function is really an infix function that can take 2+ arguments, the first of which is _always_ a real R name (not a character vector). – IRTFM Jul 06 '17 at 00:47
14

You can make modifications to anonymous functions, but there is no assignment to anonymous vectors. Even R creates temporary copies with names and you will sometimes see error messages that reflect that fact. You can read this in the R language definition on page 21 where it deals with the evaluation of expressions for "subset assignment" and for other forms of assignment:

x[3:5] <- 13:15 
# The result of this commands is as if the following had been executed 
`*tmp*` <- x 
x <- "[<-"(`*tmp*`, 3:5, value=13:15) 
rm(`*tmp*`) 

And there is a warning not to use *tmp* as an object name because it would be overwritting during the next call to [<-

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
IRTFM
  • 258,963
  • 21
  • 364
  • 487