Это не совсем полный ответ на ваш вопрос, но это начало.
Если вы посмотрите в определение языка R, вы увидите, что df[["name"]] <- 3.2
реализовано как
`*tmp*` <- df
df <- "[[<-.data.frame"(`*tmp*`, "name", value=3.2)
rm(`*tmp*`)
Таким образом, одна копия помещается в *tmp*
. Если вы позвоните debug("[[<-.data.frame")
, вы увидите, что он действительно вызывается с аргументом *tmp*
, и
tracemem()
покажет, что первое дублирование произойдет до того, как вы введете.
Функция [[<-.data.frame
является обычной функцией с таким заголовком:
function (x, i, j, value)
Эта функция вызывается как
`[[<-.data.frame`(`*tmp*`, "name", value = 3.2)
Теперь есть три ссылки на фрейм данных: df
в глобальной среде, *tmp*
во внутреннем коде и x
в этой функции. (На самом деле, есть промежуточный шаг, когда генерик вызывается, но это примитив, поэтому ему не нужно создавать новую ссылку.)
Класс x
изменяется в функции; это вызывает копию. Затем один из компонентов x
изменяется; это еще одна копия. Так что получается 3.
Просто догадываясь, я бы сказал, что причина первого дублирования в том, что сложная замена может ссылаться на исходное значение, и это исключает возможность получения частично измененного значения.