Perché l'operatore di assegnazione assegna al lato sinistro?


47

Ho iniziato a insegnare a un amico a programmare di recente (stiamo usando Python) e quando abbiamo iniziato a discutere della creazione di variabili e dell'operatore di assegnazione, mi ha chiesto perché il valore a destra è assegnato al nome a sinistra e non viceversa .

Non ci avevo pensato troppo prima, perché mi sembrava naturale, ma lei disse che da sinistra a destra le sembrava più naturale, poiché è così che la maggior parte di noi legge le lingue naturali.

Ci ho pensato e ho concluso che rende il codice molto più facile da leggere, dal momento che i nomi assegnati (a cui il programmatore dovrà riutilizzare) sono facilmente visibili, allineati a sinistra.

aligned = 2
on = 'foo' + 'bar' + 'foobar'
the = 5.0 / 2
left = 2 + 5

Al contrario di:

2 = aligned 
'foo' + 'bar' + 'foobar' = on
5.0 / 2 = the 
2 + 5 = right 

# What were the names again...?

Ora mi chiedo se ci sono anche altri motivi per questo standard. C'è una storia dietro? O c'è qualche motivo tecnico per cui questa è una buona opzione (non so molto sui compilatori)? E ci sono dei linguaggi di programmazione che assegnano al lato destro?


15
R può assegnare al lato destro ( value -> variable).
È

Forse questo è dovuto a nomi di variabili errati? Che ne dici di 'numAligned is 2` e' chickensLeft is 2 + 5 '?
Giobbe

18
Il nome del tuo amico ... Yoda?
Adrian,

1
Se inizia a lamentarsi di questo, mi chiedo cosa farà quando vedrà C ++ & co.
BlackBear

3
Solo una nota a margine : Khan Academy ha alcune lezioni su Python per programmatori principianti: khanacademy.org/#computer-science e Google ne ha alcune per più avanzate: code.google.com/edu/languages/google-python-class/set- up.html
lindon fox

Risposte:


56

Idem @paxdiablo. I primi linguaggi di programmazione sono stati scritti da matematici - in realtà lo erano tutti. In matematica, secondo il suo principio - leggere da sinistra a destra - ha senso il modo in cui funziona.

x = 2y - 4.

In matematica, diresti questo: Sia x uguale a 2y -4.

Inoltre, anche in algebra lo fai. Quando risolvi un'equazione per una variabile, isola la variabile che stai risolvendo sul lato sinistro. cioè y = mx + b;

Inoltre, una volta che un'intera famiglia di lingue, come la famiglia C, ha una certa sintassi, è più costoso cambiare.


19
@FarmBoy: in matematica, assegnazione e uguaglianza SONO la stessa cosa, in quanto non esiste una sequenza in una formula come nei computer. (a è uguale a b e allo stesso tempo b è uguale a a)
Petruza il

1
@FB tranne in alcuni linguaggi funzionali a singolo compito come ad esempio Erlang. L'assegnazione e l'assicurazione dell'uguaglianza sono le stesse della matematica
Peer Stritzinger il

18
@Petruza No, in matematica i compiti e l'uguaglianza non sono la stessa cosa. Se dico "Let x = 2y - 3" è diverso da "Così x = 2y - 3". Matematica, in genere il contesto li differenzia. Poiché il commento che mi ha contestato è stato acclamato in modo così universale, menzionerò che ho un dottorato di ricerca. in matematica, ne sono abbastanza sicuro.
Eric Wilson,

2
Non conosco la matematica da nessuna parte vicino a un dottorato di ricerca, ciò che dichiaro è che poiché non esiste sequenzialità, non esiste un ordine di esecuzione in matematica sia in un compito che in un'uguaglianza, a differenza della programmazione, in cui entrambe le parti di un compito possono essere differenti ad un certo punto nel tempo, e finiscono per essere uguali ad un altro punto nel tempo. Ma in matematica, in un compito come let a be...non c'è tempo, anche entrambi i lati del compito sono uguali, quindi il compito è in realtà un'uguaglianza, non c'è da stupirsi perché entrambi usano lo stesso segno:=
Petruza

5
@Petruzza - ma non v'è sequenzialità. I documenti matematici sono scritti dall'inizio alla fine, lo stesso di qualsiasi altro documento. Se affermo x = 1nel capitolo uno, ma affermo x = 2nel capitolo due, questa non è una terribile contraddizione: ogni affermazione si applica solo in un determinato contesto. La differenza nella programmazione imperativa è in parte la rimozione di una barriera (non abbiamo bisogno di un cambio di contesto), e in parte riguardo all'implementazione e all'utilità.
Steve314,

26

BASIC, uno dei primi linguaggi informatici aveva la forma "corretta" di:

10 LET AREA = HEIGHT * WIDTH

che corrisponde alla mentalità matematica di specificare una variabile, come "Sia H l'altezza dell'oggetto".

COBOLera anche simile con la sua COMPUTEaffermazione. Come per molti modi di fare le cose, potrebbe essere stata semplicemente una decisione arbitraria portata avanti in molte lingue.


7
Suppongo che questo modulo sia più naturale quando le linee di programma sono considerate "istruzioni" anziché "operazioni". Come in, I declare that X must equal THISinvece del più lineareEvaluate THIS and store it in X
voithos

Aspetta, BASIC era un linguaggio informatico "precoce"?
Alex Feinman,

2
@Alex Considerando che risale agli anni '60, direi che è abbastanza presto.
Ben Richards,

1
D'altra parte, in COBOL potresti scrivere MULTIPLY HEIGHT BY WIDTH GIVING AREA, quindi la variabile che ottiene il risultato si trova sul lato destro dell'istruzione.
user281377

25

In realtà, esiste un linguaggio di programmazione che assegna al lato destro: TI-BASIC ! Non solo, ma non usa '=' come operatore di assegnazione, ma utilizza piuttosto una freccia nota come operatore "STO".

esempi:

5→A
(A + 3)→B
(A - B)→C

Nell'esempio sopra, vengono dichiarate tre variabili e vengono dati valori. A sarebbe 5, B sarebbe 8 e C sarebbe -3. La prima dichiarazione / assegnazione può essere letta "store 5 as A".

Per quanto riguarda il motivo per cui TI-BASIC utilizza un tale sistema per l'assegnazione, lo attribuisco al fatto che è un linguaggio di programmazione per una calcolatrice. L'operatore "STO" sui calcolatori TI veniva spesso utilizzato nelle normali operazioni della calcolatrice dopo il calcolo di un numero. Se fosse un numero che l'utente voleva ricordare, avrebbero premuto il pulsante "STO" e il caclulator avrebbe richiesto loro un nome (attivando automaticamente il blocco alfa in modo che i tasti producessero lettere anziché numeri):

Sin(7 + Cos(3))
                    -.26979276
Ans→{variable name}
                    -.26979276

e l'utente può nominare la variabile come preferisce. Dovendo attivare il blocco alfa, digitare il nome, quindi premere "STO" e premere il tasto "Ans" sarebbe stato troppo ingombrante per le normali operazioni. Poiché tutte le funzioni della calcolatrice sono disponibili in TI-BASIC, nessun altro operatore di assegnazione è stato aggiunto poiché "STO" ha eseguito la stessa attività, anche se al contrario rispetto alla maggior parte delle altre lingue.

(Aneddoto: TI-BASIC è stata una delle prime lingue che ho imparato, quindi quando ho iniziato a studiare Java al college mi sono sentito come se l'assegnazione alla SINISTRA fosse insolita e "arretrata"!)


+1 L'ho completamente dimenticato! Anche TI Basic è stata la mia prima lingua, ma non ricordo questo dettaglio.
Barjak,

In realtà l'operatore STO è più vicino al modo in cui funziona la macchina e al modo in cui funziona qualsiasi lingua. Il valore viene prima calcolato e quindi memorizzato.
Kratz,

15

Euristico 1: di fronte a più di un modo possibile di fare qualcosa durante la progettazione di una lingua, scegli quella più comune, più intuitiva, altrimenti finirai con Perl +.

Ora, come è più naturale (almeno per un madrelingua inglese)? Diamo un'occhiata a come scriviamo / diciamo cose in inglese:

Steven ora ha 10 anni (invece di 10 anni Steven ora). Pesa più di 190 libbre (rispetto a più di 190 libbre che peso).

Nel codice:

steven = 10
i > 190

Quanto segue sembra anche più naturale:

"Se Mary ha 18 anni, allora può avere una caramella". "Se ho meno di 21 anni, chiederò a te mio fratello di tequila".

if (mary == 18) { ... }
if (i < 21) { ... }

di:

"Se 18 anni Mary è ..." "Se 21 è maggiore della mia età ..."

Ora il codice:

if (18 == mary) { ... }
if (21 > i) { ... }

Si noti che ciò non è naturale né per i programmatori né per i parlanti di lingua inglese. Le frasi sembrano yoda-speak e il codice è soprannominato yoda-condizioni. Questi potrebbero essere utili in C ++, ma sono sicuro che la maggior parte delle persone sarebbe d'accordo: se un compilatore potesse fare il lavoro pesante e alleviare la necessità di condizioni di yoda, la vita sarebbe un po 'più facile.

Certo, ci si potrebbe abituare a qualsiasi cosa. Ad esempio, il numero 81 è scritto come:

Eighty One (inglese) Eighty e one (spagnolo) One and Eighty (tedesco).

Finalmente ce ne sono 4! = 24 modi validi per dire "la mela verde giace sul tavolo" in russo - l'ordine (quasi) non ha importanza, tranne che "on" deve unirsi a "table". Quindi, se sei un madrelingua russo (per esempio), allora potresti non preoccuparti se uno scrive a = 10o 10 = aperché entrambi sembrano ugualmente naturali.

Mentre la linguistica è una materia affascinante, non l'ho mai studiata formalmente e non conosco molte lingue. Spero di aver fornito abbastanza contro-esempi.


4
... e in francese, 81 si dice "quattro volte ventuno" ... :)
Martin Sojka,

1
@Martin, credo che il danese sia molto simile.
un CVn

7
@Martin È davvero strano, perché quattro volte ventuno sono 84.
Peter Olson

6
@Peter: hai sbagliato parentesi, è(four times twenty) one
SingleNegationElimination

4
@Job: Leggendo il tuo "Se 18 anni Mary è ...", mi è stato inevitabilmente ricordato che Yoda ha detto "Quando raggiungerai il novecento, sembrerai bello, no?" in Return of the Jedi :-)
joriki il

11

È iniziato con FORTRAN negli anni '50. Dove FORTRAN era un'abbreviazione di FORmula TRANslation - le formule in questione erano semplici equazioni algebriche che per convenzione assegnano sempre a sinistra.

Il suo quasi contemporaneo COBOL invece doveva essere simile all'inglese e assegnato alla destra (per lo più!).

MOVE 1 TO COUNTER.
ADD +1 TO LINE-CNT.
MULTIPLY QTY BY PRICE GIVING ITEM-PRICE.

Penso che questo sia il miglior esempio qui perché illustra perfettamente un contesto in una lingua in cui è leggibile da un parlante inglese comune ma ha il giusto compito. Sto dicendo che è importante a causa della grande quantità di persone che dicono in inglese che leggerebbe da sinistra a destra solo perché l'incarico abbia un senso, il che non è assolutamente vero.
Joshua Hedges,

5

Bene, come ha sottolineato @ diceguyd30, ci sono entrambe le notazioni.

  • <Identifier> = <Value>significa "lascia che l' identificatore sia valore ". O per espanderlo: Definisci (o ridefinisci) la variabile Identificatore su Valore .
  • <Value> -> <Identifier>significa "store Value to Identifier ". O per espanderlo: inserisci il valore nella posizione designata dall'identificatore .

Naturalmente, in genere l' identificatore può in realtà essere qualsiasi valore L.

Il primo approccio onora il concetto astratto di variabili, il secondo approccio riguarda più l'archiviazione effettiva.

Si noti che il primo approccio è comune anche nelle lingue, che non hanno compiti. Si noti inoltre, che la definizione di variabile e l'assegnazione sono relativamente vicini <Type> <Identifier> = <Value>vs. <Identifier> = <Value>.


3

Come già accennato, abbastanza bene tutti i primi linguaggi informatici hanno funzionato in questo modo. Ad esempio FORTRAN, che è arrivato molti anni prima di BASIC.

In realtà ha molto senso avere la variabile assegnata a sinistra dell'espressione di assegnazione. In alcune lingue, potresti avere diverse routine sovraccaricate con SAME NAME, che restituiscono diversi tipi di risultati. Consentendo al compilatore di visualizzare prima il tipo della variabile assegnata, sa quale routine sovraccarica chiamare o quale cast implicito generare quando si converte da (es.) Un numero intero in un float. È una spiegazione semplicistica, ma spero che tu abbia l'idea.


2
Capisco la tua spiegazione, ma il compilatore non potrebbe solo guardare avanti fino alla fine della dichiarazione?
voithos,

Ciò potrebbe rendere il lexer più semplice nei linguaggi di oggi, ma quanti linguaggi di programmazione supportano persino i metodi denominati, per non parlare dei sovraccarichi dei metodi, quando questo tipo di sintassi era nuovo?
un CVn

2
Ciao @voithos. Sì, il compilatore potrebbe guardare al futuro, ma sarebbe stato probabilmente un livello inaccettabile di complessità nei primi giorni della scrittura del compilatore, che era spesso assemblatore codificato a mano! Penso che mettere la variabile assegnata a sinistra sia una scelta pragmatica: è più facile analizzare sia l'uomo che la macchina.
Dave Jewell,

Penso che sarebbe banale per un incarico assegnare a destra. Quando un'espressione come 3 + 4 == 6 + 7, entrambi i lati vengono valutati prima dell'operatore, poiché la lingua viene definita in modo ricorsivo. L'elemento linguaggio 'variabile = espressione', può essere facilmente modificato in 'espressione = variabile'. Il fatto che ciò provochi situazioni ambigue dipende dal resto della lingua.
Kratz,

@Kratz - questo è certamente vero per i compilatori ora, ma potrebbe esserci stato un problema minore per linguaggi interpretati molto vecchi che funzionavano con sorgente tokenizzata. OTOH, ciò avrebbe potuto favorire la variabile a destra piuttosto che la variabile a sinistra.
Steve314,

3

Potrebbe essere un residuo dei primi algoritmi di analisi. Ricorda che l'analisi del LR fu inventata solo nel 1965, e potrebbe anche essere che i parser LL avessero problemi (entro i limiti di tempo e di spazio delle macchine in quel momento) andando in senso contrario. Tener conto di:

identifier = function();
function();

I due sono chiaramente non chiariti dal secondo token. D'altro canto,

function() = identifier;
function();

Non è divertente. Questo peggiora quando inizi a nidificare le espressioni di assegnazione.

function(prev_identifier = expression) = identifier;
function(prev_identifier = expression);

Naturalmente, più facile disambiguare per le macchine significa anche più facile disambiguare per gli umani. Un altro semplice esempio potrebbe essere la ricerca dell'inizializzazione di un determinato identificatore.

identifier1 = expressionOfAnArbitraryLength;
identifier2 = expressionOfAReallyReallyReallyArbitraryLength;
identifier3 = expression;
identifier4 = AlongLineExpressionWithAFunctionCallWithAssignment(
    identifier = expr);

Facile, basta guardare in alto a sinistra. Lato destro, d'altra parte

expressionOfAnArbitraryLength = identifier1;
expressionOfAReallyReallyReallyArbitraryLength = identifier2;
expression = identifier3;
AlongLineExpressionWithAFunctionCallWithAssignment(expr = identifier
    ) = identifier4;

Soprattutto quando non puoi grepperforare le carte, è molto più difficile trovare l'identificatore che desideri.


Proprio il punto a cui avevo pensato, sì.
voithos,

2

Le lingue di assemblaggio hanno la destinazione come parte del codice operativo sinistro. Le lingue di livello superiore tendevano a seguire le convenzioni delle lingue precedenti.

Quando vedi =(o :=per i dialetti pasquali), potresti pronunciare quelli come is assigned the value, quindi la natura da sinistra a destra avrà senso (perché leggiamo anche da sinistra a destra nella maggior parte delle lingue). Poiché i linguaggi di programmazione sono stati sviluppati principalmente da persone che leggono da sinistra a destra, le convenzioni sono rimaste bloccate.

È un tipo di dipendenza dal percorso . Suppongo che se la programmazione informatica fosse stata inventata da persone che parlavano ebraico o arabo (o qualche altra lingua da destra a sinistra), allora sospetto che avremmo messo la destinazione sulla destra.


Sì, ma sospetto che anche il testo negli editor sarebbe allineato a destra ...
voithos,

8
Non puoi generalizzare così sui linguaggi degli assembly. Essi variano in base a dove si trova l'operando di destinazione.
quick_now

2
@quickly_now: giusto; in effetti, la maggior parte dei linguaggi macchina primitivi (nemmeno assemblatori secondo gli standard odierni) non aveva nemmeno destinazione, poiché di solito c'erano solo uno o due accumulatori per uso generale. la maggior parte delle operazioni implicava l'accumulatore come destinazione, ad eccezione dei codici operativi "store", che specificavano solo l'indirizzo di memoria e non l'origine (che era l'accumulatore). Non credo davvero che abbia influito sulla sintassi dell'assegnazione per le lingue simili a ALGOL.
Javier

3
@Tangurena - Alcune lingue assembler hanno la destimazione a sinistra. Non del codice operativo (che è il codice oggetto assemblato), ma a sinistra dell'elenco degli argomenti per l'istruzione mnemonica. Tuttavia, altri hanno la destinazione sulla destra. In 68000 assemblatore, dovresti scrivere mov.b #255, d0, ad esempio, dove si d0trova il registro a cui assegnare. Gli assemblatori più vecchi hanno un solo argomento per istruzione. Nel 6502 LDA #255(Load Accumulator), potresti Adire che è a sinistra, ma è anche a sinistra in STA wherever(Store Accumulator).
Steve314,

2
E persino l'Intel 4004 (l'ultimo antenato a 4 bit della famiglia 8086, con 8008 e 8080 in mezzo) è stato sviluppato dopo l' assegnazione in lingue di alto livello. Se stai assumendo che la serie 8086 sia rappresentativa di ciò che hanno fatto gli assemblatori negli anni '50 e precedenti, dubito fortemente che sia vero.
Steve314,

2

Per quel che vale, la maggior parte delle dichiarazioni in COBOL leggono da sinistra a destra, in modo che i due operandi sono stati nominati prima, e la destinazione ultima, come: multiply salary by rate giving tax.

Non suggerirò comunque che il tuo studente potrebbe preferire COBOL, per paura di essere (giustamente) segnalato per fare un commento così basso, non sincero e insipido! :-)


1

ha detto che da sinistra a destra le sembrava più naturale, poiché è così che la maggior parte di noi legge le lingue naturali.

Penso che questo sia un errore. Da un lato, puoi dire "assegna 10 a x" o "sposta 10 a x". D'altra parte, puoi dire "imposta x su 10" o "x diventa 10".

In altre parole, a seconda della scelta del verbo, la variabile assegnata a potrebbe essere o meno il soggetto e potrebbe essere o meno sulla sinistra. Quindi "ciò che è naturale" dipende solo interamente dalla tua abituale scelta di parole per rappresentare il compito.


0

In pseudocodice l'operatore di assegnazione è molto comunemente scritto a destra. Per esempio

2*sqrt(x)/(3+y) -> z

Nei calcolatori Casio, anche varianti non programmabili, la variabile di assegnazione viene visualizzata sulla destra

A+2B → C

In Forth anche la variabile è sulla destra

expression variable !

In x86, la sintassi Intel ha la destinazione a sinistra, ma la sintassi GAS inverte l'ordine, creando confusione per molte persone, in particolare sulle istruzioni relative all'ordine dei parametri come sottrazione o confronti. Queste istruzioni sono le stesse in 2 dialetti diversi

mov rax, rbx    ; Intel syntax
movq %rbx, %rax ; GAS syntax

Entrambi spostano il valore in rbx su rax. Nessun altro linguaggio di assemblaggio che conosco scriva la destinazione sulla destra come GAS.

Alcune piattaforme mettono l'espressione a sinistra e la variabile a destra:

MOVE expression TO variable      COBOL
expression → variable            TI-BASIC, Casio BASIC
expression -> variable           BETA, R
put expression into variable     LiveCode

https://en.wikipedia.org/wiki/Assignment_%28computer_science%29#Notation

La maggior parte delle lingue assegna il valore a sinistra, uno dei motivi è facile da allineare gli operatori, più facile da leggere e riconoscere la variabile, poiché gli operatori di assegnazione e le posizioni delle variabili non varieranno selvaggiamente nelle righe, ed è più facile da leggere come msgstr "lascia che la variabile sia un valore".

Tuttavia, alcune persone preferiscono dire "sposta il valore da x a y" e scrivono la variabile sulla destra.


-1

Penso che segua un modo logico di pensare.
Prima deve esserci una casella (variabile), quindi inserire un oggetto (valore) al suo interno.
Non metti l'oggetto in aria e poi metti una scatola attorno ad esso.


2
si. nella maggior parte delle lingue il lato destro viene valutato prima di quello sinistro.
Javier

3
È una specie di "guida sul lato destro della strada". Sembra logico ma solo perché è il modo in cui l'hai sempre fatto. Tutti i paesi superiori guidano a sinistra.
James Anderson,

1
@JamesAnderson paesi superiori? : o
nawfal,

Hai ragione, è logico per un sistema di scrittura da sinistra a destra come l'alfabeto romano, che immagino sia usato da quasi tutti i linguaggi di programmazione, se non da tutti.
Petruza,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.