References

library(insitu)

Introduction

A major issue with by-reference modification is that it pays no mind to other objects which may point to the object to be changed.

Usually when you modify an object in R, it is copied. This copy means that other variables will still point to the original and remain unchanged.

When modifying by-reference, R is not informed that the contents are changed, no copy is made so all variables which pointed to the original object remain as-is, but the memory that they pointed to has changed.

This means that variables can behave in unexpected ways, and you must know which variables are pointing to the memory you are about to change.

R copy-on-modify

In the following standard R code,

  • an object x is created
  • when first assigned to a new object y, both objects point to the exact same object in memory.
  • when y is modified, a copy of the original object is created at a new memory location
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create an object and assign it to a variable
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x <- c(1, 2, 3)
y <- x

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Check the address of these objects. They are currently the same!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rlang::obj_address(x)
#> [1] "0x563a65a008a8"
rlang::obj_address(y)
#> [1] "0x563a65a008a8"


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Mutate 'y' - which means R will copy it and then change it
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
y[1] <- 8

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# x and y are now different
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x
#> [1] 1 2 3
y
#> [1] 8 2 3

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Addresses are currently different
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rlang::obj_address(x)
#> [1] "0x563a65a008a8"
rlang::obj_address(y)
#> [1] "0x563a65c723b8"

Modification in-place

In the following code

  • an object x is created
  • when first assigned to a new object y, both objects point to the exact same object in memory.
  • when y is modified by-reference, it still points to the same memory as before.
  • x and y still point to the same memory, which has changed
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create an object and assign it to a variable
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x <- c(1, 2, 3)
y <- x

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Check the address of these objects. They are currently the same!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rlang::obj_address(x)
#> [1] "0x563a672baed8"
rlang::obj_address(y)
#> [1] "0x563a672baed8"


#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Mutate 'y' - which means R will copy it and then change it
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
br_copy(y, 1, n = 1, xi = 2)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# x has changed because the underlying memory has changed!
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
x
#> [1] 1 1 3
y
#> [1] 1 1 3

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Addresses are still the same
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
rlang::obj_address(x)
#> [1] "0x563a672baed8"
rlang::obj_address(y)
#> [1] "0x563a672baed8"