Quali sono le differenze tra gli operatori di assegnazione =
e <-
in R?
Come mostra il tuo esempio, =
e <-
hanno una precedenza leggermente diversa dall'operatore (che determina l'ordine di valutazione quando sono mescolati nella stessa espressione). In effetti, ?Syntax
in R fornisce la seguente tabella di precedenza degli operatori, dal più alto al più basso:
…
‘-> ->>’ rightwards assignment
‘<- <<-’ assignment (right to left)
‘=’ assignment (right to left)
…
Ma questa è l'unica differenza?
Dato che stavi chiedendo degli operatori di assegnazione : sì, questa è l'unica differenza. Tuttavia, verrai perdonato per aver creduto diversamente. Anche la documentazione R ?assignOps
afferma che esistono più differenze:
L'operatore <-
può essere utilizzato ovunque, mentre l'operatore =
è consentito solo al livello superiore (ad esempio, nell'espressione completa digitata al prompt dei comandi) o come una delle sottoespressioni in un elenco di espressioni rinforzate.
Non mettiamoci un punto troppo fine: la documentazione R è (sottilmente) sbagliata [ 1 ] . Questo è facile da mostrare: dobbiamo solo trovare un contro-esempio =
dell'operatore che non sia (a) al livello più alto, né (b) una sottoespressione in un elenco rinforzato di espressioni (cioè {…; …}
). - Senza ulteriori indugi:
x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1
Chiaramente abbiamo eseguito un incarico, usando =
, al di fuori dei contesti (a) e (b). Quindi, perché la documentazione di una funzione di linguaggio R di base è stata errata per decenni?
È perché nella sintassi di R il simbolo =
ha due significati distinti che si confondono abitualmente:
- Il primo significato è come operatore di assegnazione . Questo è tutto ciò di cui abbiamo parlato finora.
- Il secondo significato non è un operatore ma piuttosto un token di sintassi che segnala un argomento denominato che passa in una chiamata di funzione. A differenza
=
dell'operatore che non esegue alcuna azione in fase di runtime, cambia semplicemente il modo in cui un'espressione viene analizzata.
Vediamo.
In qualsiasi parte di codice del modulo generale ...
‹function_name›(‹argname› = ‹value›, …)
‹function_name›(‹args›, ‹argname› = ‹value›, …)
... il =
è il segno che definisce il nome argomento passa: è non l'operatore di assegnazione. Inoltre, =
è del tutto vietato in alcuni contesti sintattici:
if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …
Uno di questi genererà un errore "imprevisto" = "in ‹bla›".
In qualsiasi altro contesto, si =
riferisce alla chiamata dell'operatore di assegnazione. In particolare, il semplice mettere tra parentesi la sottoespressione rende valido quanto sopra (a) e (b) un incarico . Ad esempio, il seguente esegue il compito:
median((x = 1 : 10))
Ma anche:
if (! (nf = length(from))) return()
Ora potresti obiettare che tale codice è atroce (e potresti avere ragione). Ma ho preso questo codice dalla base::file.copy
funzione (sostituendolo <-
con =
) - è un modello pervasivo in gran parte della base di codice R di base.
La spiegazione originale di John Chambers , su cui probabilmente si basa la documentazione R, in realtà lo spiega correttamente:
[il =
compito è] consentito solo in due punti della grammatica: al livello superiore (come programma completo o espressione digitata dall'utente); e quando isolato dalla struttura logica circostante, mediante parentesi graffe o una coppia extra di parentesi.
Una confessione: ho mentito prima. V'è una differenza ulteriore tra il =
e <-
operatori: che chiamano funzioni distinte. Per impostazione predefinita, queste funzioni fanno la stessa cosa ma è possibile sovrascriverle separatamente per modificare il comportamento. Al contrario, <-
e ->
(assegnazione da sinistra a destra), sebbene sintatticamente distinti, chiamano sempre la stessa funzione. Sovrascrivere l'uno prevale anche sull'altro. Sapere questo è raramente pratico ma può essere usato per alcuni divertenti shenanigans .
<-
simbolo provengono da vecchie tastiere APL che in realtà avevano un solo<-
tasto su di esse.