Каковы различия между "=" и "<-" в R? - PullRequest
631 голосов
/ 16 ноября 2009

Чем отличаются операторы присваивания = и <- в R?

Я знаю, что операторы немного отличаются, как показывает этот пример

x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"

Но это единственная разница?

Ответы [ 7 ]

620 голосов
/ 16 ноября 2009

Разница в операторах присваивания становится понятнее, когда вы используете их для установки значения аргумента в вызове функции. Например:

median(x = 1:10)
x   
## Error: object 'x' not found

В этом случае x объявляется в области действия функции, поэтому он не существует в рабочей области пользователя.

median(x <- 1:10)
x    
## [1]  1  2  3  4  5  6  7  8  9 10

В этом случае x объявляется в рабочей области пользователя, поэтому вы можете использовать его после завершения вызова функции.


В сообществе R существует общее предпочтение использовать <- для назначения (кроме подписей функций) для совместимости с (очень) старыми версиями S-Plus. Обратите внимание, что пробелы помогают прояснить такие ситуации, как

x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3

Большинство RE IDE имеют сочетания клавиш для упрощения ввода <-. Ctrl + = в Architect, Alt + - в RStudio ( Опция + - под macOS), Shift + - (подчеркивание) в emacs + ESS.


Если вы предпочитаете писать от = до <-, но хотите использовать более распространенный символ назначения для общедоступного кода (например, в CRAN), тогда вы можете использовать один из tidy_* функции в пакете formatR для автоматической замены = на <-.

library(formatR)
tidy_source(text = "x=1:5", arrow = TRUE)
## x <- 1:5

Ответ на вопрос «Почему x <- y = 5 выдает ошибку, а не x <- y <- 5?» "Это зависит от магии, содержащейся в парсере". Синтаксис R содержит много неоднозначных случаев , которые должны быть решены так или иначе. Анализатор выбирает разрешение битов выражения в разных порядках в зависимости от того, был ли использован = или <-.

Чтобы понять, что происходит, вам нужно знать, что назначение молча возвращает назначенное значение. Вы можете увидеть это более четко, явно напечатав, например, print(x <- 2 + 3).

Во-вторых, понятнее, если мы будем использовать префиксную нотацию для присваивания. Итак

x <- 5
`<-`(x, 5)  #same thing

y = 5
`=`(y, 5)   #also the same thing

Парсер интерпретирует x <- y <- 5 как

`<-`(x, `<-`(y, 5))

Мы можем ожидать, что x <- y = 5 будет тогда

`<-`(x, `=`(y, 5))

но на самом деле это интерпретируется как

`=`(`<-`(x, y), 5)

Это связано с тем, что = имеет более низкий приоритет, чем <-, как показано на странице справки ?Syntax.

97 голосов
/ 16 ноября 2009

Руководство по стилю Google R упрощает проблему, запрещая "=" для назначения. Неплохой выбор.

https://google.github.io/styleguide/Rguide.xml

Руководство R подробно описывает все 5 операторов присваивания.

http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html

31 голосов
/ 10 сентября 2014

x = y = 5 эквивалентно x = (y = 5), потому что операторы присваивания «группируют» справа налево, что работает. Значение: присвойте 5 y, оставив число 5; а затем присвойте это 5 x.

Это не то же самое, что (x = y) = 5, который не работает! Значение: присвоить значение y значению x, оставив значение y; а затем назначить 5, хм ..., что именно?

Когда вы смешиваете различные типы операторов присваивания, <- связывается сильнее, чем =. Так что x = y <- 5 интерпретируется как x = (y <- 5), что имеет смысл.

К сожалению, x <- y = 5 интерпретируется как (x <- y) = 5, что не работает!

См. ?Syntax и ?assignOps для определения приоритета (связывания) и правил группировки.

30 голосов
/ 28 января 2011

По словам Джона Чамберса, оператор = разрешен только на «верхнем уровне», что означает, что он не разрешен в управляющих структурах, таких как if, что делает следующую ошибку программирования недопустимой.

> if(x = 0) 1 else x
Error: syntax error

Как он пишет, «Запрещение новой формы назначения [=] в выражениях управления позволяет избежать ошибок программирования (например, в примере выше), которые более вероятны при использовании оператора равенства, чем при других назначениях S.»

Вы можете сделать это, если он «изолирован от окружающей логической структуры, скобками или дополнительной парой скобок», так что if ((x = 0)) 1 else x будет работать.

См. http://developer.r -project.org / equalAssign.html

24 голосов
/ 27 июля 2018

Чем отличаются операторы присваивания = и <- в R?

Как показывает ваш пример, = и <- имеют слегка различающийся приоритет операторов (который определяет порядок вычисления, когда они смешиваются в одном выражении). Фактически, ?Syntax в R дает следующую таблицу приоритетов операторов, от самого высокого до самого низкого:

…
‘-> ->>’           rightwards assignment
‘<- <<-’           assignment (right to left)
‘=’                assignment (right to left)
…

Но это единственная разница?

Поскольку вы спрашивали об операторах присваивания : да, это единственное отличие. Тем не менее, вы были бы прощены за то, что поверили в обратное. Даже документация R ?assignOps утверждает, что есть больше различий:

Оператор <- может использоваться где угодно, тогда как оператор = разрешен только на верхнем уровне (например, в полном выражении, набранном из командной строки) или как единое целое подвыражений в ограниченном списке выражений.

Давайте не будем особо подчеркивать: Документация R (тонко) неверна [ 1 ] . Это легко показать: нам просто нужно найти контрпример примера оператора =, который не является (a) на верхнем уровне и (b) подвыражением в ограниченном списке выражений (т.е. {…; …} ). - Без лишних слов:

x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1

Очевидно, что мы выполнили задание, используя =, вне контекста (a) и (b). Итак, почему документация о ядре языка R была неправильной в течение десятилетий?

Это потому, что в синтаксисе R символ = имеет два разных значения, которые обычно смешиваются:

  1. Первое значение как оператор присваивания . Это все, о чем мы говорили до сих пор.
  2. Второе значение - это не оператор, а синтаксический маркер , который сигнализирует именованный аргумент, передавая в вызове функции. В отличие от оператора =, он не выполняет никаких действий во время выполнения, он просто изменяет способ анализа выражения.

Посмотрим.

В любом куске кода общего вида…

<i>‹function_name›</i>(<i>‹argname›</i> <b>=</b> <i>‹value›</i>, …)
<i>‹function_name›</i>(<i>‹args›</i>, <i>‹argname›</i> <b>=</b> <i>‹value›</i>, …)

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

if (<i>‹var›</i> <b>=</b> <i>‹value›</i>) …
while (<i>‹var›</i> <b>=</b> <i>‹value›</i>) …
for (<i>‹var›</i> <b>=</b> <i>‹value›</i> in <i>‹value2›</i>) …
for (<i>‹var1›</i> in <i>‹var2›</i> <b>=</b> <i>‹value›</i>) …

Любое из них вызовет ошибку «неожиданно» = «in‹ bla ›».

В любом другом контексте = относится к вызову оператора присваивания. В частности, простое размещение скобок вокруг подвыражения делает любое из вышеперечисленного (а) действительным и (б) присваиванием . Например, следующее выполняет присваивание:

median((x = 1 : 10))

Но также:

if (! (nf = length(from))) return()

Теперь вы можете возразить, что такой код ужасен (и вы можете быть правы). Но я взял этот код из функции base::file.copy (заменив <- на =) - это распространенный шаблон в большей части базовой кодовой базы R.

Оригинальное объяснение Джона Чемберса , на котором, вероятно, основана документация R, действительно объясняет это правильно:

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


Признание: я солгал раньше. - это еще одно отличие между операторами = и <-: они вызывают разные функции. По умолчанию эти функции делают то же самое, но вы можете переопределить любую из них отдельно, чтобы изменить поведение. Напротив, <- и -> (присвоение слева направо), хотя и синтаксически различны, всегда вызывают одинаковую функцию. Переопределение одного переопределяет другое. Знание этого редко бывает практичным , но можно использовать для некоторых забавных махинаций .

22 голосов
/ 16 ноября 2009

Операторы <- и = присваивают среде, в которой они оцениваются. Оператор <- может использоваться где угодно, , тогда как оператор = допускается только на верхнем уровне (например, в полном выражении, введенном в командной строке) или как одно из подвыражений в ограниченном списке выражений.

5 голосов
/ 11 декабря 2016

Это также может добавить к пониманию разницы между этими двумя операторами:

df <- data.frame(
      a = rnorm(10),
      b <- rnorm(10)
)

Для первого элемента R присвоены значения и собственное имя, а название второго элемента выглядит немного странно.

str(df)
# 'data.frame': 10 obs. of  2 variables:
#  $ a             : num  0.6393 1.125 -1.2514 0.0729 -1.3292 ...
#  $ b....rnorm.10.: num  0.2485 0.0391 -1.6532 -0.3366 1.1951 ...

R версия 3.3.2 (2016-10-31); macOS Sierra 10.12.1

...