Каковы различия между операторами присваивания =
и <-
в R?
Я знаю, что операторы немного отличаются, как показывает этот пример
x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"
Но единственная ли это разница?
r
assignment-operator
r-faq
csgillespie
источник
источник
<-
символа приходят от старых APL клавиатур , которые фактически имели один<-
ключ на них.Ответы:
Как ваш пример показывает,
=
и<-
имеют несколько иной приоритет оператора (который определяет порядок вычисления , когда они смешиваются в одном выражении). На самом деле,?Syntax
в R выдает следующую таблицу приоритетов операторов, от высшего к низшему:Но единственная ли это разница?
Поскольку вы спрашивали об операторах присваивания : да, это единственная разница. Тем не менее, вы были бы прощены за то, что поверили в обратное. Даже документация R
?assignOps
утверждает, что есть больше различий:Давайте не будем заострять внимание на этом: документация на R (слегка) неверна [ 1 ] . Это легко показать: нам просто нужно найти контрпример для
=
оператора, который не (а) не находится на верхнем уровне и не (b) является подвыражением в ограниченном списке выражений (то есть{…; …}
). - Без дальнейших церемоний:Ясно, что мы выполнили присваивание
=
вне контекста (a) и (b). Итак, почему документация о ядре языка R была неправильной в течение десятилетий?Это потому, что в синтаксисе R символ
=
имеет два разных значения, которые обычно смешиваются:=
оператора, он не выполняет никаких действий во время выполнения, он просто изменяет способ анализа выражения.Посмотрим.
В любой части кода общего вида ...
...
=
это токен, который определяет передачу именованного аргумента: это не оператор присваивания. Кроме того,=
полностью запрещено в некоторых синтаксических контекстах:Любое из них вызовет ошибку «неожиданно» = «в‹ bla ›».
В любом другом контексте
=
относится к вызову оператора присваивания. В частности, простое размещение скобок вокруг подвыражения делает любое из вышеперечисленного (а) действительным и (б) назначением . Например, следующее выполняет назначение:Но и:
Теперь вы можете возразить, что такой код ужасен (и вы можете быть правы). Но я взял этот код из
base::file.copy
функции (заменив<-
на=
) - это распространенный шаблон в большей части основной кодовой базы R.Оригинальное объяснение Джона Chambers , которым документация по R, вероятно , на основе, на самом деле объясняет это правильно:
Признание: я солгал раньше. Там является одна дополнительная разница между
=
и<-
операторами: они называют различные функции. По умолчанию эти функции делают то же самое, но вы можете переопределить любую из них отдельно, чтобы изменить поведение. В отличие от этого,<-
и->
(назначение слева направо), хотя синтаксически различны, всегда вызывают одну и ту же функцию. Переопределение одного переопределяет другое. Знание этого редко бывает практичным, но его можно использовать для забавных махинаций .источник
?
фактически находится между ними=
и<-
, что имеет важные последствия при переопределении?
, и практически ни при чем другом.main/gram.y
), приоритет?
правильно задокументирован и ниже, чем оба,=
и<-
.=
нужно пройти специальную обработку, прежде чем будет построено дерево разбора. Может быть, связано с аргументами функции, имеет смысл, чтоfoo(x = a ? b)
мы будем искать,=
прежде чем анализировать остальную часть выражения.Разница в операторах присваивания более очевидна, когда вы используете их для установки значения аргумента в вызове функции. Например:
В этом случае
x
объявляется в рамках функции, поэтому он не существует в рабочей области пользователя.В этом случае
x
объявляется в рабочей области пользователя, поэтому вы можете использовать его после завершения вызова функции.В сообществе R есть общее предпочтение использовать
<-
для назначения (кроме подписей функций) совместимость со (очень) старыми версиями S-Plus. Обратите внимание, что пробелы помогают прояснить такие ситуации, какБольшинство RE IDE имеют сочетания клавиш для
<-
упрощения ввода. Ctrl+ =в Architect, Alt+ -в RStudio ( Option+ -под macOS), Shift+ -(подчеркивание) в emacs + ESS.Если вы предпочитаете писать
=
на<-
но хотите использовать более общий символ присваивания для публично выпущенной коды (на CRAN, например), то вы можете использовать одну изtidy_*
функций вformatR
пакете для автоматической замены=
с<-
.Ответ на вопрос «Почему
x <- y = 5
выкидывает ошибку, а нетx <- y <- 5
?» "Это зависит от магии, содержащейся в парсере". Синтаксис R содержит много неоднозначных случаев, которые должны быть решены так или иначе. Синтаксический анализатор выбирает разрешить биты выражения в различных порядках в зависимости от того ,=
или<-
был использован.Чтобы понять, что происходит, вам нужно знать, что назначение молча возвращает назначенное значение. Вы можете увидеть это более четко, например, явно печатая
print(x <- 2 + 3)
.Во-вторых, понятнее, если мы будем использовать префиксную нотацию для присваивания. Так
Парсер интерпретирует
x <- y <- 5
какМы можем ожидать,
x <- y = 5
что тогда будетно на самом деле это интерпретируется как
Это связано с тем, что
=
приоритет меньше<-
, чем показано на?Syntax
странице справки.источник
median((x = 1:10))
не менее, имеет тот же эффект, что иmedian(x <- 1:10)
.x <- x = 5
его интерпретируют, немного неверно: в действительности R интерпретирует его как`<-<-`(x, y = 5, value = 5)
(что само по себе более или менее эквивалентноtmp <- x; x <- `<-<-`(tmp, y = 5, value = 5)
). Хлоп!=
при вызове функции , не выполняет присваивание и не является оператором присваивания. Это совершенно отличное синтаксическое выражение R, которое использует один и тот же символ. Кроме того, код, который вы показываете, не «объявляется»x
в области действия функции. В объявлении функции выполняет указанное заявление. Вызов функции не делает (с именованными...
аргументами это немного усложняется ).Руководство по стилю Google R упрощает проблему, запрещая "=" для назначения. Неплохой выбор.
https://google.github.io/styleguide/Rguide.xml
Руководство R подробно описывает все 5 операторов присваивания.
http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html
источник
x<-y
когдаx < -y
подразумевалось, раздражает меня так сильно, что я лично предпочитаю=
. Наличие вашего кода зависит от наличия пробелов, мне не кажется хорошим. Можно рекомендовать интервалы в качестве совета по стилю, но для того, чтобы ваш код работал по-другому, есть ли пробел или нет? Что, если вы переформатируете свой код или воспользуетесь поиском и заменой, пробельные символы могут иногда исчезать и код будет ошибочным. Это не проблема с=
. IIUC, запрещающий=
приравнивается к требованию "<-
"; т.е. 3 символа, включая пробел, а не просто "<-
".TRUE
R. Поэтому, если вы намереваетесь проверить, еслиx
оно меньше-y
, вы можете написать,if (x<-y)
что не будет предупреждать или выдавать ошибку, и, похоже, будет работать нормально. Это будет толькоFALSE
тогдаy=0
, когда.=
и используете<-
, трудно утверждать, что дополнительный шагgrep "[^<]<-[^ ]" *.R
не требуется.=
не нужно такогоgrep
.<-
если вы можете использовать=
? В 99,99% случаев=
это нормально. Иногда вам нужно,<<-
хотя, это другая история.x = y = 5
эквивалентноx = (y = 5)
, потому что операторы присваивания "группа" справа налево, который работает. Значение: присвоить 5y
, оставив число 5; а затем назначьте это 5x
.Это не то же самое
(x = y) = 5
, что не работает! Значение: присвойте значениеy
tox
, оставив значениеy
; а затем назначить 5, хм ... что именно?Когда вы смешиваете различные виды операторов присваивания,
<-
связываете жестче, чем=
. Такx = y <- 5
интерпретируется какx = (y <- 5)
, что имеет смысл.К сожалению,
x <- y = 5
это интерпретируется как(x <- y) = 5
, что не работает!Смотрите
?Syntax
и?assignOps
правила приоритета (привязки) и группировки.источник
<- <<-
выше=
в таблице приоритетов, что означает, что<-
будет выполнено в первую очередь. Итак,x <- y = 5
должно быть выполнено как(x <- y) = 5
.По словам Джона Чемберса, оператор
=
допускается только на «верхнем уровне», что означает, что он не допускается в управляющих структурах, напримерif
, делает следующую ошибку программирования недопустимой.Как он пишет, «Запрещение новой формы присваивания [=] в управляющих выражениях позволяет избежать ошибок программирования (таких как приведенный выше пример), которые более вероятны при использовании оператора равенства, чем при других присваиваниях S».
Вы можете сделать это, если он «изолирован от окружающей логической структуры, фигурными скобками или дополнительной парой скобок», так
if ((x = 0)) 1 else x
будет работать.Смотрите http://developer.r-project.org/equalAssign.html
источник
x==0
почти всегда подразумевается вместо этого.x=0
качестве задания надx<-0
!=
как можно меньше , потому=
и==
выглядят так похожи.if(x = 0) 1 else x
выдает ошибку, помогая мне найти и исправить ошибку.if(x <- 1) 1 else x
не выдает ошибку и очень сбивает с толку.else
значение, вы хотели написать его таким образом?», Но это может быть несбыточной мечтой ...Операторы
<-
и=
назначают в среду, в которой они оцениваются. Оператор<-
может использоваться где угодно, тогда как оператор=
допускается только на верхнем уровне (например, в полном выражении, набранном в командной строке) или в качестве одного из подвыражений в ограниченном списке выражений.источник
x <- 42
по себе это утверждение; вif (x <- 42) {}
нем было бы выражение, и оно недействительно. Чтобы было ясно, это не имеет никакого отношения к тому, находитесь ли вы в глобальной среде или нет.1 + (x = 2)
function() x = 1
,repeat x = 1
,if (TRUE) x = 1
....Это также может добавить к пониманию разницы между этими двумя операторами:
Для первого элемента R присвоены значения и собственное имя, тогда как имя второго элемента выглядит несколько странно.
Версия R 3.3.2 (2016-10-31); macOS Sierra 10.12.1
источник
data.frame
пытается использовать имя предоставленной переменной в качестве имени элемента во фрейме данных)make.names("b <- rnorm(10)")
.