R, глубокий против.мелкие копии, передача по ссылке
-
11-12-2019 - |
Вопрос
Я хотел бы понять логику, которую R использует при передаче аргументов функциям, создании копий переменных и т. д.что касается использования памяти.Когда он фактически создает копию переменной vs.просто передать ссылку на эту переменную?В частности, меня интересуют следующие ситуации:
f <- function(x) {x+1}
a <- 1
f(a)
Является a
передается буквально или это ссылка на передаваемую информацию?
x <- 1
y <- x
Ссылка на копию?Когда это не так?
Если бы кто-нибудь мог объяснить мне это, я был бы очень признателен.
Решение
Когда он проходит переменные, он всегда является копией, а не посредством ссылки. Иногда, однако, вы не получите копию, сделанную, пока на самом деле не произойдет назначение. Реальное описание процесса - это пропуск. Посмотрите на документацию
?force
?delayedAssign
.
Одно практическое значение состоит в том, что очень трудно, если не невозможно избежать нужды, по крайней мере, вдвое больше баран, сколько ваши объекты номинально занимают. Изменение большого объекта, как правило, требует внесения временной копии.
Обновление: 2015: Я делаю (и сделал) согласиться с Matt Delyle, что его пакет Data.table предоставляет альтернативное маршруту для присваивания, которое позволяет избежать проблемы дублирования копирования. Если это было запрошенное обновление, то я не понял его в то время, когда было сделано предложение.
Было недавнее изменение в R 3.2.1 в правилах оценки для apply
и Reduce
. Это было так объявлено со ссылкой на новости здесь: Интересная статья, цитирующая Jetzel в комментариях, теперь здесь :
Другие советы
Поздний ответ, но это очень важный аспект языкового дизайна, который недостаточно освещается в Интернете (или, по крайней мере, в обычных источниках).
x <- c(0,4,2)
lobstr::obj_addr(x)
# [1] "0x7ff25e82b0f8"
y <- x
lobstr::obj_addr(y)
# [1] "0x7ff25e82b0f8"
Обратите внимание на одинаковый «адрес памяти», т.е.место в памяти, где хранится объект.Таким образом, вы можете подтвердить, что x
и y
оба указывают на один и тот же идентификатор.
Книга Хэдли Уикхема Advanced R касается этого:
Рассмотрим этот код:
x <- c(1, 2, 3)
Это легко прочитать так:«Создайте объект с именем« X », содержащий значения 1, 2 и 3».К сожалению, это упрощение, которое приведет к неточным прогнозам о том, что на самом деле делает R за кулисами.Более точно сказать, что этот код делает две вещи:
Он создает объект, вектор значений,
c(1, 2, 3)
.И это связывает этот объект с именем,x
.Другими словами, объект или значение не имеют имени;на самом деле значение имеет имя.
Обратите внимание, что эти адреса памяти являются эфемерными и меняются с каждым новым сеансом R.
Теперь вот важная часть.
В семантике R объекты копируются по значению.Это означает, что изменение копии оставляет исходный объект нетронутым.Поскольку копирование данных в памяти является дорогой операцией, копии в R максимально ленивы.Они происходят только тогда, когда новый объект действительно изменяется.Источник:[Документация по языку R][1]
Итак, если мы теперь изменим значение y
добавляя значение к вектору, y
теперь указывает на другой «объект».Это согласуется с тем, что говорится в документации относительно операции копирования, происходящей «только при изменении нового объекта» (ленивый). y
указывает на другой адрес, чем был раньше.
y <- c(y, -3)
print(lobstr::obj_addr(y))
# [1] "0x7ff25e825b48"