R, глубокие или мелкие копии, проходят по ссылке

Я хотел бы понять, что логика R используется при передаче аргументов в функции, создании копий переменных и т.д. в отношении использования памяти. Когда он действительно создает копию переменной или просто передает ссылку на эту переменную? В частности, мне интересны ситуации:

f <- function(x) {x+1}
a <- 1
f(a)

Проставляется ли a буквально или является ссылкой на переданное сообщение?

x <- 1
y <- x

Ссылка на копию? Когда это не так?

Если бы кто-то мог объяснить это мне, я был бы очень признателен.

Ответы

Ответ 1

Когда он передает переменные, он всегда копируется, а не ссылкой. Иногда, однако, вы не получите копию, пока на самом деле не произойдет присвоение. Реальное описание процесса - это обещание. Взгляните на документацию

?force
?delayedAssign

Одним из практических последствий является то, что очень сложно, если не невозможно, избежать необходимости в том, чтобы, по крайней мере, вдвое больше ОЗУ, чем ваши номинально занимают ваши объекты. Для изменения большого объекта обычно требуется сделать временную копию.

update: 2015: Я (и сделал) согласен с Мэттом Доулом в том, что его пакет data.table предоставляет альтернативный маршрут для назначения, который позволяет избежать проблемы дублирования копирования. Если это было запрошено обновление, тогда я не понял его в то время, когда было сделано предложение.

В правилах оценки для apply и Reduce произошла недавняя смена в R 3.2.1. Это было SO-анонсировано со ссылкой на News here: Возвращение анонимных функций из приложения - что происходит не так?

И интересная статья, приведенная jhetzel в комментариях, теперь здесь:

Ответ 2

Поздний ответ, но очень важный аспект языкового дизайна, который недостаточно освещается в Интернете (или, по крайней мере, в обычных источниках).

x <- c(0,4,2)
lobstr::obj_addr(x)
# [1] "0x7ff25e82b0f8"
y <- x
lobstr::obj_addr(y)
# [1] "0x7ff25e82b0f8"

Обратите внимание на идентичный "адрес памяти", то есть место в памяти, где хранится объект. Таким образом, вы можете подтвердить, что x и y оба указывают на один и тот же идентификатор.

Книга Хэдли Уикхэма Продвинутый R касается:

Consider this code:

x <- c(1, 2, 3)

Его легко прочитать как: "создать объект с именем‘ x, содержащий значения 1, 2 и 3 '. К сожалению, это упрощение, которое приведет к неточным прогнозам о том, что R на самом деле делает за кулисами. Точнее сказать, что этот код выполняет две вещи:

Это создание объекта, вектора значений, c(1, 2, 3). И это привязка этого объекта к имени, x. Другими словами, объект или значение, не имеет имени; на самом деле это имя, которое имеет значение.

Обратите внимание, что они являются адресами памяти, эфемерны и меняются с каждым новым R сеансом.

Теперь вот важная часть.

В семантике R объекты копируются по значению. Это означает, что изменение копия оставляет исходный объект без изменений. Поскольку копирование данных в Операция с памятью - дорогая операция, копии в R настолько ленивы, насколько это возможно. Они происходят только тогда, когда новый объект действительно модифицирован. Источник: [Документация по языку] [1]

Поэтому, если мы теперь изменим значение y, добавив значение к вектору, y теперь будет указывать на другой "объект". Это согласуется с тем, что в документации говорится о том, что операция копирования происходит "только при изменении нового объекта" (ленивый). y указывает на другой адрес, чем был ранее.

y <- c(y, -3)
print(lobstr::obj_addr(y))
# [1] "0x7ff25e825b48"