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"