How does the `[<-` function work in R?
Asked Answered
C

2

8

I've seen a couple of people using [<- as a function with Polish notation, for example

x <- matrix(1:4, nrow = 2)
`[<-`(x, 1, 2, 7)

which returns

     [,1] [,2]
[1,]    1    7
[2,]    2    4

I've tried playing around with [<- a little, and it looks like using it this way prints the result of something like x[1,2] <- 7 without actually performing the assignment. But I can't figure out for sure what this function actually does, because the documentation given for ?"[" only mentions it in passing, and I can't search google or SO for "[<-".

And yes, I know that actually using it is probably a horrible idea, I'm just curious for the sake of a better understanding of R.

Chimp answered 1/2, 2016 at 20:15 Comment(4)
It's more like R converts x[1,2] <- 7 to be x <- '[<-'(x, 1, 2, 7).Sikorski
If you understand the [ function and the <- function, then the [<- function makes a lot of sense. Try [(x,1,2). Try <-(a,1)Croon
I'm not seeing this a duplicate. I thought question is why [<- doesn't actually effect a sub-assignment in the symbol/named object x. That did not appear to be the question posed in the nominated duplicate.Drier
"[<-" is a function that returns the accordingly modified object. That is what "[<-"(x, i, value) seems to do. To see the difference between the explicit "[<-" call and how x[i] <- value is parsed, perhaps, see '*tmp*' = "tmp"; x = 1:3; x[2] <- 0; x; get("*tmp*") VS '*tmp*' = "tmp"; x = 1:3; "[<-"(x, 2, 0); x; get("*tmp*") as noted here.Quillan
D
4

This is what you would need to do to get the assignment to stick:

 `<-`(    `[`(   x, 1, 2), 7)  # or x <- `[<-`(   x, 1, 2, 7)
 x
     [,1] [,2]
[1,]    1    7
[2,]    2    4

Essentially what is happening is that [ is creating a pointer into row-col location of x and then <- (which is really a synonym for assign that can also be used in an infix notation) is doing the actual "permanent" assignment. Do not be misled into thinking this is a call-by-reference assignment. I'm reasonably sure there will still be a temporary value of x created.

Your version did make a subassignment (as can be seen by what it returned) but that assignment was only in the local environment of the call to [<- which did not encompass the global environment.

Drier answered 1/2, 2016 at 21:3 Comment(2)
Is x[1,2]<-7 a call-by-reference then?Clerical
Nope. That will create a temporary value as well. Most "regular R" assignments are call by promise which is more like call-by-value than call by reference. The data.table package does modifications of its objects in place. The R6 mechanism was set up to provide more direct access to objects and prevent copying overhead.Drier
C
2

Since `[`(x, y) slices an object, and `<-`(x, z) performs assignment, it seems like `[<-`(x,y,z) would perform the assignment x[y] <- y. @42-'s answer is a great explanation of what [<- actually does, and the top answer to `levels<-`( What sorcery is this? provides some insight into why R works this way.

To see what [<- actually does under the hood, you have to go to the C source code, which for [<- can be found at http://svn.r-project.org/R/trunk/src/main/subassign.c (the relevant parts start at around line 1470). You can see that x, the object being "assigned to" is protected so that only the local version is mutated. Instead, we're using VectorAssign, MatrixAssign, ArrayAssign, etc. to perform assignment locally and then returning the result.

Chimp answered 1/2, 2016 at 23:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.