Jakie są różnice między operatorami przypisania =
a <-
R?
Jak pokazuje twój przykład =
i <-
mają nieco inny priorytet dla operatora (który określa kolejność obliczeń, gdy są mieszane w tym samym wyrażeniu). W rzeczywistości ?Syntax
w R podaje następującą tabelę pierwszeństwa operatorów, od najwyższej do najniższej:
…
‘-> ->>’ rightwards assignment
‘<- <<-’ assignment (right to left)
‘=’ assignment (right to left)
…
Ale czy to jedyna różnica?
Ponieważ pytałeś o operatory przypisania : tak, to jedyna różnica. Jednakże wybaczono by ci, że wierzysz inaczej. Nawet dokumentacja R ?assignOps
twierdzi, że istnieje więcej różnic:
Operator <-
może być używany w dowolnym miejscu, podczas gdy operator =
jest dozwolony tylko na najwyższym poziomie (np. W pełnym wyrażeniu wpisanym w wierszu polecenia) lub jako jedno z podwyrażeń na usztywnionej liście wyrażeń.
Nie podkreślmy zbyt dobrze: dokumentacja R jest (subtelnie) błędna [ 1 ] . Łatwo to pokazać: musimy po prostu znaleźć kontrprzykład =
operatora, który nie jest (a) na najwyższym poziomie, ani (b) podwyrażenie na usztywnionej liście wyrażeń (tj {…; …}
.). - Bez ceregieli:
x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1
Wyraźnie wykonaliśmy zadanie, używając =
poza kontekstami (a) i (b). Dlaczego więc dokumentacja podstawowej funkcji języka R jest błędna przez dziesięciolecia?
To dlatego, że w składni R symbol =
ma dwa różne znaczenia, które rutynowo się łączą:
- Pierwsze znaczenie to operator przypisania . To wszystko, o czym do tej pory rozmawialiśmy.
- Drugim znaczeniem nie jest operator, lecz token składniowy, który sygnalizuje nazwany argument przekazujący wywołanie funkcji. W przeciwieństwie do
=
operatora, nie wykonuje żadnych działań w czasie wykonywania, zmienia jedynie sposób, w jaki wyrażenie jest analizowane.
Zobaczmy.
W dowolnym kodzie ogólnej formy…
‹function_name›(‹argname› = ‹value›, …)
‹function_name›(‹args›, ‹argname› = ‹value›, …)
... The =
jest znak, który definiuje nazwany argumentem uchwala: jest to nie operator przypisania. Ponadto =
jest całkowicie zabronione w niektórych kontekstach składniowych:
if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …
Każdy z nich spowoduje błąd „nieoczekiwany” = „w ‹bla›”.
W każdym innym kontekście =
odnosi się do wywołania operatora przypisania. W szczególności samo umieszczenie nawiasów wokół podwyrażenia powoduje, że dowolne z powyższych (a) jest ważne i (b) przypisanie . Na przykład następujące zadania wykonuje przypisanie:
median((x = 1 : 10))
Ale również:
if (! (nf = length(from))) return()
Teraz możesz sprzeciwić się, że taki kod jest okropny (i możesz mieć rację). Ale wziąłem ten kod z base::file.copy
funkcji (zastąpienie <-
z =
) - jest to wzór wszechobecne w dużej części kodzie rdzeń R.
Oryginalne wyjaśnienie przez John Chambers , którego dokumentacja R jest prawdopodobnie w oparciu o właściwie wyjaśnia to poprawnie:
[ =
przypisanie jest dozwolone] tylko w dwóch miejscach gramatyki: na najwyższym poziomie (jako kompletny program lub wyrażenie wpisane przez użytkownika); a po odizolowaniu od otaczającej struktury logicznej za pomocą nawiasów klamrowych lub dodatkowej pary nawiasów.
Wyznanie: skłamałem wcześniej. Tam jest jeden dodatkowy różnica między =
i <-
operatorów: nazywają różne funkcje. Domyślnie te funkcje robią to samo, ale można zastąpić każdą z nich osobno, aby zmienić zachowanie. Natomiast <-
i ->
(przypisanie od lewej do prawej), chociaż odrębne pod względem składniowym, zawsze wywołuje tę samą funkcję. Przesłonięcie jednego powoduje również zastąpienie drugiego. Wiedza o tym jest rzadko praktyczna, ale może być wykorzystana do zabawy z shenaniganami .
<-
symbolu pochodzi od starych klawiatur APL, które faktycznie miały jeden<-
klawisz.