Подтвердить что ты не робот

Почему использование назначить плохо?

Этот пост (Ленивая оценка в R - влияет ли назначение?) Охватывает некоторые общие точки, но я не уверен, что он отвечает на мой вопрос.

Я прекратил использование assign когда обнаружил семейство apply некоторое время назад, хотя и исключительно по причинам элегантности в таких ситуациях:

names.foo <- letters
values.foo <- LETTERS
for (i in 1:length(names.foo))
  assign(names.foo[i], paste("This is: ", values.foo[i]))

который можно заменить на:

foo <- lapply(X=values.foo, FUN=function (k) paste("This is :", k))
names(foo) <- names.foo

Это также причина этого (http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-turn-a-string-into-a-variable_003f) R-faq говорит, что этого следует избегать.

Теперь я знаю, что assign обычно осуждается. Но есть ли другие причины, о которых я не знаю? Я подозреваю, что это может испортить обзор или ленивую оценку, но я не уверен? Пример кода, который демонстрирует такие проблемы, будет отличным.

4b9b3361

Ответ 1

На самом деле эти две операции совершенно разные. Первый дает вам 26 разных объектов, а второй дает вам только один. Второй объект будет намного проще использовать в анализах. Поэтому, я думаю, я бы сказал, что вы уже продемонстрировали существенный недостаток assign, а именно необходимость необходимости всегда использовать get для корреляции или сбора всех одинаково названных отдельных объектов, которые теперь "потеряны" в глобальном Окружающая среда. Попробуйте представить, как вы будете последовательно делать что-либо с этими 26 отдельными объектами. Для второй стратегии будет достаточно простого lapply(foo, func).

В этом разделе часто задаваемых вопросов говорится, что использование присваивания, а затем назначение имен проще, но не означает, что это было "плохо". Я считаю, что это "менее функционально", поскольку вы фактически не возвращаете значение, которое присваивается. Эффект выглядит побочным эффектом (и в этом случае стратегия assign приводит к 26 отдельным побочным эффектам). Использование assign, по-видимому, принимается людьми, которые поступают с языков, имеющих глобальные переменные, как способ избежать подбора "True R Way", то есть функционального программирования с объектами данных. Они действительно должны учиться использовать списки, а не засорять рабочее пространство с помощью отдельных элементов.

Существует еще одна парадигма назначения, которая может быть использована:

 foo <- setNames(  paste0(letters,1:26),  LETTERS)

Это создает именованный атомный вектор, а не именованный список, но доступ к значениям в векторе по-прежнему выполняется с именами, указанными в [.

Ответ 2

В качестве источника fortune(236) я подумал, что добавлю пару примеров (также см. fortune(174)).

Во-первых, опрос. Рассмотрим следующий код:

x <- 1
y <- some.function.that.uses.assign(rnorm(100))

После запуска вышеуказанных двух строк кода, каково значение x?

Функция assign используется для фиксации "действия на расстоянии" (см. http://en.wikipedia.org/wiki/Action_at_a_distance_ (computer_programming ) или google для него). Это часто является источником трудностей для поиска ошибок.

Я думаю, что самая большая проблема с assign заключается в том, что она приводит людей к путям мышления, которые отвлекают их от лучших вариантов. Простым примером является 2 набора кода в вопросе. Решение lapply более элегантно и должно поощряться, но тот факт, что люди узнают о функции assign, приводит людей к опции цикла. Затем они решают, что им нужно выполнить одну и ту же операцию для каждого объекта, созданного в цикле (это было бы просто еще одна простая lapply или sapply, если бы использовалось элегантное решение) и прибегнуть к еще более сложному циклу, включающему как get и apply вместе с уродливыми вызовами на paste. Затем те, кто влюблен в assign, пытаются сделать что-то вроде:

curname <- paste('myvector[', i, ']')
assign(curname, i)

И это не делает то, что они ожидали, что приводит к жалобам на R (что так же справедливо, как жаловаться на то, что мой соседний соседний дом слишком далеко, потому что я решил пройти долгий путь вокруг блока) или даже хуже, углубиться в использование eval и parse, чтобы заставить их построенную строку "работать" (что затем приводит к fortune(106) и fortune(181)).

Ответ 3

Я хотел бы указать, что assign предназначен для использования с environment s.

С этой точки зрения "плохая" вещь в приведенном выше примере использует не совсем подходящую структуру данных (базовая среда вместо list или data.frame, vector,...).

Боковое примечание: также для environment s, работают операторы $ и $<-, поэтому во многих случаях явные assign и get там не нужны.