Почему data.table определен: = а не перегрузка <-?

data.table ввел оператор: =. Почему бы не перегрузить < -?

Ответ 1

Я не думаю, что есть какая-то техническая причина, по которой это необходимо, по следующей причине: := используется только внутри [...], поэтому он всегда цитируется. [...] проходит через дерево выражений, чтобы увидеть, есть ли в нем :=.

Это означает, что он не действует как оператор и не перегружен; поэтому они могли бы выбрать практически любого оператора, которого они хотели. Думаю, может быть, это выглядело лучше? Или менее запутанным, потому что это явно не <-?

(Обратите внимание, что если := использовалось вне [...], это не могло быть <-, потому что вы не можете перегрузить <-. <- Не оценивает его аргумент lefthand, t знать, что такое тип).

Ответ 2

Есть два места, которые <- могут быть "перегружены":

x[i, j] <- value           # 1
x[i, {colname <- value}]   # 2

Первая копирует все x в *tmp*, меняет рабочую копию и возвращает x. Это вещь R (src/main/eval.c и subassign.c) обсуждалась недавно на r-devel здесь. Казалось, что возможно изменить R, чтобы позволить пакетам или самому R избежать этой копии до *tmp*, но в настоящее время это невозможно, IIUC.

Во-вторых, это то, о чем говорит Оуэн. Если вы согласны с тем, что это нормально для выполнения задания по ссылке в j, как это, то какой оператор? Согласно комментарию к ответу Оуэна, <- и <<- уже используются пользователями в j, поэтому мы нажимаем :=.

Даже если [<- не скопировал все x, нам все равно нравится := в j, поэтому мы можем делать такие вещи:

DT[,{newcol1:=sum(a)
     newcol2:=a/newcol1}, by=group]

Если новые столбцы добавляются посредством ссылки на таблицу, а RHS каждого := оценивается внутри каждой группы. (Когда: = внутри группы реализовано.)


Обновление Oct 2012

Начиная с 1.8.2 (по CRAN в июле 2012 года), := по группе была реализована для добавления или обновления отдельных столбцов; то есть одиночный LHS :=. И теперь в v1.8.3 (по R-Forge на момент написания) несколько столбцов могут быть добавлены группой; например.

DT[, c("newcol1","newcol2") := .(sum(a),sum(b)), by=group]

или, возможно, более элегантно:

DT[,`:=`(newcol1=sum(a),
         newcol2=sum(b)), by=group]

Но итеративный множественный RHS, предполагаемый на некоторое время, где второе выражение может использовать результат из первого, еще не реализовано (FR # 1492). Таким образом, это все равно приведет к ошибке "newcol1 not found" и должно быть выполнено в два этапа:

DT[,`:=`(newcol1=sum(a),
         newcol2=a/newcol1), by=group]