Які відмінності між операторами призначення =
і <-
в R?
Як показує ваш приклад, =
і <-
мають дещо інший пріоритет оператора (що визначає порядок оцінки, коли вони змішуються в одному виразі). Фактично, ?Syntax
в R подається наступна таблиця пріоритетності оператора, від найвищої до найнижчої:
…
‘-> ->>’ rightwards assignment
‘<- <<-’ assignment (right to left)
‘=’ assignment (right to left)
…
Але хіба це єдина різниця?
Оскільки ви запитували про операторів призначення : так, це єдина різниця. Однак вам би пробачили, що вірите в інше. Навіть документація R ?assignOps
стверджує, що існує більше відмінностей:
Оператор <-
може бути використаний будь-де, тоді як оператор =
дозволений лише на верхньому рівні (наприклад, у повному виразі, набраному в командному рядку) або в якості одного з піддепресій у скопленому списку виразів.
Не будемо ставити на нього занадто точну крапку: документація на R (тонко) неправильна [ 1 ] . Це легко показати: нам просто потрібно знайти зустрічний приклад =
оператора, який не є (а) на верхньому рівні, а також (b) суб-вираження у скопленому списку виразів (тобто {…; …}
). - Без зайвого галасу:
x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1
Ясно, що ми виконали завдання, використовуючи =
поза контекстами (a) та (b). Отже, чому документація основної функції мови R протягом десятиліть помилялася?
Це тому, що в синтаксисі R символ =
має два різних значення, які регулярно плутаються:
- Перше значення - як оператор присвоєння . Це все, про що ми говорили поки що.
- Другий сенс - це не оператор, а швидше синтаксичний маркер, який сигналізує з назвою аргументу, що передається у виклику функції. На відміну від
=
оператора, він не виконує жодних дій під час виконання, він просто змінює спосіб аналізу вираження.
Подивимось.
У будь-якому фрагменті коду загальної форми ...
‹function_name›(‹argname› = ‹value›, …)
‹function_name›(‹args›, ‹argname› = ‹value›, …)
… =
Знак - це маркер, який визначає названий аргумент, що передається: це не оператор присвоєння. Крім того, =
цілком заборонено в деяких синтаксичних контекстах:
if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …
Будь-яке з них призведе до помилки "несподівано" = "у ‹bla›".
У будь-якому іншому контексті =
відноситься до призначення виклику оператора. Зокрема, лише встановлення круглих дужок навколо підвираження робить будь-яке з перерахованих вище пунктів (а) дійсним та (b) призначенням . Наприклад, наступне виконує завдання:
median((x = 1 : 10))
Але також:
if (! (nf = length(from))) return()
Тепер ви можете заперечити, що такий код жорстокий (і ви можете мати рацію). Але я взяв цей код із base::file.copy
функції (замінивши<-
з =
) - це всеосяжний стиль в більшій частині ядра R кодову.
Оригінальне пояснення Джона Chambers , яким документація по R, ймовірно , на основі, на самому ділі пояснює це правильно:
[ =
присвоєння] дозволено лише у двох місцях граматики: на верхньому рівні (як повноцінна програма або вираз, введений користувачем); і коли вони ізольовані від оточуючої логічної структури, дужками або додатковою парою дужок.
Зізнання: я брехав раніше. Там є одна додаткова різниця між =
і <-
операторами: вони називають різні функції. За замовчуванням ці функції роблять те саме, але ви можете змінити будь-яку з них окремо, щоб змінити поведінку. Навпаки, <-
і ->
(призначення зліва направо), хоч і синтаксично виразні, завжди викликають одну і ту ж функцію. Переосмислення одного також перекриває інше. Знаючи це, рідко буває практично, але це може бути використано для веселих шенагіганів .
<-
символу походить від старих клавіатур APL, які насправді мали на собі одну<-
клавішу.