Copy On Modify; What Happens When You Run This Code? x <- list(1:10); x[[2]] <- x

Maybe this will help. Here we use pryr::address to see the memory location where objects are stored (note, your actual addresses may vary, but when I have matching addresses, your addresses should match as well).

library(pryr)
x <- list(1:10)
pryr::address(x)
# [1] "0x3452810"
y <- x[[1]]
pryr::address(y)
# [1] "0x16b53bf0"

So we have an list x at a given location. We can think of lists in R as collections of pointers to other objects. We can't directly take the address of where it's storing it's first item (at least, I don't know how with address), but we can store that value to y and since R will only change address when objects are modified, we can assume this is where that first value is stored. Now let's update x

x[[2]] <- x
pryr::address(x)
# [1] "0x16001018"

we can see that x has changed and been given a new memory location

y <- x[[1]]
pryr::address(y)
# [1] "0x16b53bf0"

Note that the first element though is still at the same memory address. So a new copy of this vector hasn't been made. The new list just points to that same vector. Now let's look at the address of the value we just added

y <- x[[2]]
pryr::address(y)
# [1] "0x3452810"

Note that this value now points to the old memory address where the original x lived.

And further more

y <- x[[2]][[1]]
pryr::address(y)
# [1] "0x16b53bf0"

both lists point to the same 1:10 vector. It's only stored once.

So when you do x[[2]]<-x what you are doing is creating a new list. This new list contains two "pointers" essentially. One to the same vector that was in the original list, and one that points to the original address of the list.


x <- list(1:10) there you create a list. Let's inspect it using str()

> str(x)
List of 1
 $ : int [1:10] 1 2 3 4 5 6 7 8 9 10

Then you assign this list to next position in the list. Such as x[[2]] <- x. Now the list x contains:

> str(x)
List of 2
 $ : int [1:10] 1 2 3 4 5 6 7 8 9 10
 $ :List of 1
  ..$ : int [1:10] 1 2 3 4 5 6 7 8 9 10

To check what's going on. I check the type of x and x[[2]]

> typeof(x) 
[1] "list"
> typeof(x[[2]])
[1] "list"

As a result, x is a list which contains a list.

Update

I used ref() function from lobstr packages.

> x <- list(1:10)
> ref(x)
o <1:0x344642b8> [list]
\-<2:0x20ad2588> [int]

> x[[2]] <- x
> ref(x)
o <1:0x34aee7e0> [list]
+-<2:0x20ad2588> [int]
\-o <3:0x344642b8> [list]
  \-<2:0x20ad2588> [int]

The result shows that the value corresponds to the same memory location.

Tags:

List

Copy

R