Espressione contro dichiarazione

Sto chiedendo riguardo al c #, ma presumo che sia lo stesso nella maggior parte delle altre lingue.

Qualcuno ha una buona definizione di espressioni e affermazioni e quali sono le differenze?

Espressione: qualcosa che valuta un valore. Esempio: 1 + 2 / x
Dichiarazione: una linea di codice che fa qualcosa. Esempio: GOTO 100

Nei primi linguaggi di programmazione generica, come FORTRAN, la distinzione era cristallina. In FORTRAN, una dichiarazione era una unità di esecuzione, una cosa che hai fatto. L’unica ragione per cui non si chiamava “linea” era perché a volte si estendeva su più righe. Un’espressione da sola non poteva fare nulla … dovevi assegnarla a una variabile.

1 + 2 / X

è un errore in FORTRAN, perché non fa nulla. Dovevi fare qualcosa con quell’espressione:

X = 1 + 2 / X

FORTRAN non aveva una grammatica come la conosciamo oggi: quell’idea fu inventata, insieme a Backus-Naur Form (BNF), come parte della definizione di Algol-60. A quel punto la distinzione semantica (“avere un valore” contro “fare qualcosa”) era racchiusa nella syntax : un tipo di frase era un’espressione, e un altro era un’affermazione, e il parser poteva distinguerli.

I progettisti di lingue successive hanno offuscato la distinzione: hanno consentito alle espressioni sintattiche di fare cose e hanno consentito affermazioni sintattiche con valori. Il primo esempio di linguaggio popolare che sopravvive ancora è C. I progettisti di C si sono resi conto che non è stato fatto alcun danno se ti è stato permesso di valutare un’espressione e buttare via il risultato. In C, ogni espressione sintattica può essere trasformata in un’affermazione semplicemente virando un punto e virgola lungo la fine:

1 + 2 / x;

è una dichiarazione totalmente legittima anche se assolutamente non accadrà nulla. Allo stesso modo, in C, un’espressione può avere effetti collaterali – può cambiare qualcosa.

1 + 2 / callfunc(12);

perché callfunc potrebbe semplicemente fare qualcosa di utile.

Una volta che si consente a qualsiasi espressione di essere un’istruzione, è ansible consentire l’operatore di assegnazione (=) all’interno delle espressioni. Ecco perché C ti permette di fare cose del genere

callfunc(x = 2);

Questo valuta l’espressione x = 2 (assegnando il valore di 2 a x) e quindi passa quello (il 2) alla funzione callfunc .

Questa confusione di espressioni e dichiarazioni si verifica in tutte le derivate C (C, C ++, C # e Java), che hanno ancora alcune istruzioni (come while ) ma che consentono di usare quasi qualsiasi espressione come istruzione (solo in C # assignment , le espressioni call, increment e decrement possono essere usate come dichiarazioni, vedere la risposta di Scott Wisniewski ).

Avere due “categorie sintattiche” (che è il nome tecnico per il genere di affermazioni ed espressioni della cosa) può portare a una duplicazione degli sforzi. Ad esempio, C ha due forms di condizionale, la forma dell’affermazione

 if (E) S1; else S2; 

e la forma dell’espressione

 E ? E1 : E2 

E a volte le persone vogliono la duplicazione che non c’è: nella C standard, ad esempio, solo un’istruzione può dichiarare una nuova variabile locale, ma questa capacità è abbastanza utile che il compilatore C GNU fornisce un’estensione GNU che consente a un’espressione di dichiarare un variabile locale pure.

I designer di altri linguaggi non amavano questo tipo di duplicazione e hanno visto fin da subito che se le espressioni possono avere effetti collaterali e valori, allora la distinzione sintattica tra le espressioni e le espressioni non è tutto ciò che è utile, quindi se ne sono liberati . Haskell, Icon, Lisp e ML sono tutte lingue che non hanno istruzioni sintattiche, hanno solo espressioni. Anche il ciclo strutturato della class e le forms condizionali sono considerate espressioni e hanno valori, ma non molto interessanti.

Vorrei fare una piccola correzione alla risposta di Joel sopra.

C # non consente a tutte le espressioni di essere utilizzate come dichiarazioni. In particolare, solo le espressioni di assegnazione, chiamata, incremento e decremento possono essere utilizzate come dichiarazioni.

Ad esempio, il compilatore C # contrassegna il seguente codice come errore di syntax:

1 + 2;

  • un’espressione è tutto ciò che produce un valore: 2 + 2
  • una dichiarazione è uno dei “blocchi” di base dell’esecuzione del programma.

Nota che in C “=” è in realtà un operatore, che fa due cose:

  • restituisce il valore della sottoespressione della mano destra.
  • copia il valore della sottoespressione della mano destra nella variabile sul lato sinistro.

Ecco un estratto dalla grammatica ANSI C. Puoi vedere che C non ha molti diversi tipi di affermazioni … la maggior parte delle affermazioni in un programma sono affermazioni di espressioni, cioè un’espressione con un punto e virgola alla fine.

 statement : labeled_statement | compound_statement | expression_statement | selection_statement | iteration_statement | jump_statement ; expression_statement : ';' | expression ';' ; 

http://www.lysator.liu.se/c/ANSI-C-grammar-y.html

Un’espressione è qualcosa che restituisce un valore, mentre un’istruzione non lo fa.

Per esempio:

 1 + 2 * 4 * foo.bar() //Expression foo.voidFunc(1); //Statement 

Il grande affare tra i due è che puoi concatenare le espressioni insieme, mentre le dichiarazioni non possono essere incatenate.

Puoi trovarlo su wikipedia , ma le espressioni vengono valutate con un certo valore, mentre le istruzioni non hanno alcun valore valutato.

Pertanto, le espressioni possono essere utilizzate nelle dichiarazioni, ma non viceversa.

Nota che alcune lingue (come Lisp, e credo Ruby, e molte altre) non differenziano la dichiarazione rispetto all’espressione … in questi linguaggi, tutto è un’espressione e può essere incatenato con altre espressioni.

Per una spiegazione delle importanti differenze di componibilità (concatenazione) delle espressioni rispetto alle dichiarazioni, il mio riferimento preferito è il premio del premio Turing di John Backus, la programmazione Can può essere liberata dallo stile di von Neumann? .

I linguaggi imperativi (Fortran, C, Java, …) enfatizzano le istruzioni per strutturare i programmi e hanno espressioni come una sorta di ripensamento. I linguaggi funzionali enfatizzano le espressioni. I linguaggi puramente funzionali hanno espressioni così potenti che le affermazioni possono essere eliminate del tutto.

Semplicemente: un’espressione valuta un valore, un’asserzione no.

Le espressioni possono essere valutate per ottenere un valore, mentre le istruzioni non restituiscono un valore (sono di tipo vuoto ).

Anche le espressioni di chiamata di funzione possono essere considerate dichiarazioni, naturalmente, ma a meno che l’ambiente di esecuzione non abbia una variabile built-in speciale per contenere il valore restituito, non c’è modo di recuperarlo.

I linguaggi orientati alle istruzioni richiedono che tutte le procedure siano un elenco di dichiarazioni. I linguaggi orientati alle espressioni, che probabilmente sono tutti linguaggi funzionali, sono elenchi di espressioni o, nel caso di LISP, una lunga espressione S che rappresenta un elenco di espressioni.

Sebbene entrambi i tipi possano essere composti, la maggior parte delle espressioni può essere composta arbitrariamente purché i tipi corrispondano. Ogni tipo di affermazione ha il proprio modo di comporre altre affermazioni, se possono farlo tutte. Foreach e if le istruzioni richiedono una singola dichiarazione o che tutte le dichiarazioni subordinate vadano in un blocco di istruzioni, una dopo l’altra, a meno che le sottostazioni non consentano le proprie sottostazioni.

Le dichiarazioni possono anche includere espressioni, in cui un’espressione non include alcuna affermazione. Un’eccezione, tuttavia, sarebbe un’espressione lambda, che rappresenta una funzione, e quindi può includere qualsiasi cosa che una funzione può contenere a meno che il linguaggio non consenta solo lambda limitati, come i lambda di espressione singola di Python.

In un linguaggio basato su espressioni, tutto ciò che serve è una singola espressione per una funzione poiché tutte le strutture di controllo restituiscono un valore (molti restituiscono NIL). Non c’è bisogno di una dichiarazione di ritorno poiché l’espressione valutata da ultimo nella funzione è il valore di ritorno.

Alcune cose sui linguaggi basati sull’espressione:


Più importante: tutto restituisce un valore


Non c’è differenza tra parentesi graffe e parentesi graffe per delimitare i blocchi di codice e le espressioni, poiché tutto è un’espressione. Ciò non impedisce tuttavia lo scoping lessicale: potrebbe essere definita una variabile locale per l’espressione in cui è contenuta la sua definizione e tutte le istruzioni contenute al suo interno, ad esempio.


In un linguaggio basato su espressioni, tutto restituisce un valore. Questo può essere un po ‘strano all’inizio – Cosa restituisce (FOR i = 1 TO 10 DO (print i)) ?

Alcuni semplici esempi:

  • (1) restituisce 1
  • (1 + 1) restituisce 2
  • (1 == 1) restituisce TRUE
  • (1 == 2) restituisce FALSE
  • (IF 1 == 1 THEN 10 ELSE 5) restituisce 10
  • (IF 1 == 2 THEN 10 ELSE 5) restituisce 5

Un paio di esempi più complessi:

  • Alcune cose, come alcune chiamate di funzione, in realtà non hanno un valore significativo da restituire (cose che producono solo effetti collaterali?). Chiamando OpenADoor(), FlushTheToilet() o TwiddleYourThumbs() restituirà una sorta di valore banale, come OK, Done o Success.
  • Quando più espressioni non collegate vengono valutate all’interno di un’espressione più grande, il valore dell’ultima cosa valutata nell’espressione grande diventa il valore dell’espressione grande. Per prendere l’esempio di (FOR i = 1 TO 10 DO (print i)) , il valore del ciclo for è “10”, fa sì che l’espressione (print i) venga valutata 10 volte, ogni volta restituendo i come stringa. L’ultima volta attraverso i resi 10 , la nostra risposta finale

Spesso richiede un leggero cambiamento di mentalità per ottenere il massimo da un linguaggio basato sull’espressione, dal momento che tutto è un’espressione che rende ansible “incorporare” un sacco di cose

Come esempio veloce:

  FOR i = 1 to (IF MyString == "Hello, World!" THEN 10 ELSE 5) DO ( LotsOfCode ) 

è un sostituto perfettamente valido per le non basate su espressioni

 IF MyString == "Hello, World!" THEN TempVar = 10 ELSE TempVar = 5 FOR i = 1 TO TempVar DO ( LotsOfCode ) 

In alcuni casi, il layout che il codice basato sulle espressioni consente mi sembra molto più naturale

Certo, questo può portare alla pazzia. Come parte di un progetto di hobby in un linguaggio di scripting basato su espressioni chiamato MaxScript, sono riuscito a creare questa monster line

 IF FindSectionStart "rigidifiers" != 0 THEN FOR i = 1 TO (local rigidifier_array = (FOR i = (local NodeStart = FindsectionStart "rigidifiers" + 1) TO (FindSectionEnd(NodeStart) - 1) collect full_array[i])).count DO ( LotsOfCode ) 

Una dichiarazione è un caso speciale di un’espressione, una con tipo non void . La tendenza delle lingue a trattare le affermazioni in modo diverso spesso causa problemi, e sarebbe meglio se fossero correttamente generalizzate.

Ad esempio, in C # abbiamo l’utilissimo Func set sovraccaricato di delegati generici. Ma dobbiamo anche impostare una corrispondente Action , e la programmazione di ordine generale di ordine generale deve essere ripetuta costantemente per far fronte a questa sfortunata biforcazione.

Esempio banale: una funzione che controlla se un riferimento è nullo prima di chiamare su un’altra funzione:

 TResult IfNotNull(TValue value, Func func) where TValue : class { return (value == null) ? default(TValue) : func(value); } 

Potrebbe il compilatore affrontare la possibilità di TResult essere void ? Sì. Tutto ciò che deve fare è richiedere che il ritorno sia seguito da un’espressione che è di tipo void . Il risultato di default(void) sarebbe di tipo void e la funzione passata avrebbe bisogno della forma Func (che sarebbe equivalente a Action ).

Una serie di altre risposte implicano che non è ansible concatenare affermazioni come è ansible con le espressioni, ma non sono sicuro da dove venga questa idea. Possiamo pensare a ; che appare dopo le istruzioni come operatore di infissi binari, prendendo due espressioni di tipo void e combinandole in un’unica espressione di tipo void .

Istruzioni -> Istruzioni da seguire in sequenza
Espressioni -> Valutazione che restituisce un valore

Le istruzioni sono fondamentalmente come passi o istruzioni in un algoritmo, il risultato dell’esecuzione di un’istruzione è l’attualizzazione del puntatore dell’istruzione (cosiddetto in assembler)

Le espressioni non implicano e l’ordine di esecuzione a prima vista, il loro scopo è quello di valutare e restituire un valore. Nei linguaggi di programmazione imperativi la valutazione di un’espressione ha un ordine, ma è solo a causa del modello imperativo, ma non è la loro essenza.

Esempi di dichiarazioni:

 for goto return if 

(tutti implicano l’avanzamento della linea (dichiarazione) di esecuzione su un’altra linea)

Esempio di espressioni:

 2+2 

(non implica l’idea di esecuzione, ma della valutazione)

Le dichiarazioni sono frasi grammaticalmente complete. Le espressioni non lo sono. Per esempio

 x = 5 

legge come “x ottiene 5.” Questa è una frase completa. Il codice

 (x + 5)/9.0 

legge “x plus 5 tutto diviso per 9.0”. Questa non è una frase completa. La dichiarazione

 while k < 10: print k k += 1 

è una frase completa. Si noti che l'intestazione del ciclo non lo è; "while k <10," è una clausola subordinata.

Dichiarazione ,

Una dichiarazione è un blocco procedurale da cui sono costruiti tutti i programmi C #. Un’istruzione può dichiarare una variabile locale o una costante, chiamare un metodo, creare un object o assegnare un valore a una variabile, una proprietà o un campo.

Una serie di istruzioni circondate da parentesi graffe formano un blocco di codice. Un corpo del metodo è un esempio di un blocco di codice.

 bool IsPositive(int number) { if (number > 0) { return true; } else { return false; } } 

Le dichiarazioni in C # contengono spesso espressioni. Un’espressione in C # è un frammento di codice che contiene un valore letterale, un nome semplice o un operatore e i suoi operandi.

Espressione ,

Un’espressione è un frammento di codice che può essere valutato su un singolo valore, object, metodo o spazio dei nomi. I due tipi più semplici di espressioni sono letterali e nomi semplici. Un valore letterale è un valore costante che non ha nome.

 int i = 5; string s = "Hello World"; 

Sia i che s sono semplici nomi che identificano le variabili locali. Quando tali variabili vengono utilizzate in un’espressione, il valore della variabile viene recuperato e utilizzato per l’espressione.

Preferisco il significato statement nel senso logico formale della parola. È uno che cambia lo stato di una o più variabili nel calcolo, consentendo di fare una dichiarazione vera o falsa sul loro valore (i).

Immagino che ci sarà sempre confusione nel mondo informatico e nella scienza in generale quando vengono introdotte nuove terminologie o parole, le parole esistenti sono “riproposte” o gli utenti ignorano la terminologia esistente, stabilita o “corretta” per quello che stanno descrivendo

Non sono davvero soddisfatto di nessuna delle risposte qui. Ho esaminato la grammatica per C ++ (ISO 2008) . Tuttavia, forse per motivi di didattica e programmazione, le risposte potrebbero essere sufficienti per distinguere i due elementi (la realtà sembra tuttavia più complicata).

Una dichiarazione consiste di zero o più espressioni, ma può anche essere altri concetti linguistici. Questo è il modulo Extended Backus Naur per la grammatica (estratto per estratto conto):

 statement: labeled-statement expression-statement <-- can be zero or more expressions compound-statement selection-statement iteration-statement jump-statement declaration-statement try-block 

Possiamo vedere gli altri concetti che sono considerati dichiarazioni in C ++.

  • espressione-affermazione s è auto-esplicativa (una dichiarazione può essere costituita da zero o più espressioni, leggere attentamente la grammatica, è difficile)
  • case per esempio è una dichiarazione etichettata
  • la selezione-istruzione s è if if/else
  • iteration-statement s while do...while , for (...)
  • jump-statement s sono break , continue , return (può restituire espressione), goto
  • dichiarazione-dichiarazione è l'insieme delle dichiarazioni
  • try-block è una dichiarazione che rappresenta try/catch blocchi try/catch
  • e potrebbe esserci qualcosa in più nella grammatica

Questo è un estratto che mostra la parte espressioni:

 expression: assignment-expression expression "," assignment-expression assignment-expression: conditional-expression logical-or-expression assignment-operator initializer-clause throw-expression 
  • le espressioni sono o contengono spesso assegnazioni
  • espressione condizionale (suona fuorviante) si riferisce all'utilizzo degli operatori ( + , - , * , / , & , | , && , || , ...)
  • espressione del tiro - eh? anche la clausola del throw è un'espressione

Ecco l’estate di una delle risposte più semplici che ho trovato.

originariamente risposto da Anders Kaseorg

Una dichiarazione è una riga completa di codice che esegue un’azione, mentre un’espressione è una qualsiasi sezione del codice che valuta un valore.

Le espressioni possono essere combinate “orizzontalmente” in espressioni più grandi usando operatori, mentre le istruzioni possono essere combinate solo “verticalmente” scrivendo una dopo l’altra o con costrutti di blocchi.

Ogni espressione può essere utilizzata come una dichiarazione (il cui effetto è valutare l’espressione e ignorare il valore risultante), ma la maggior parte delle istruzioni non può essere utilizzata come espressione.

http://www.quora.com/Python-programming-language-1/Whats-the-difference-between-a-statement-and-an-expression-in-Python

Per migliorare e convalidare la mia risposta precedente, le definizioni dei termini del linguaggio di programmazione dovrebbero essere spiegate dalla teoria del tipo di informatica, quando applicabile.

Un’espressione ha un tipo diverso dal tipo Bottom, cioè ha un valore. Una dichiarazione ha il tipo Unit o Bottom.

Da ciò ne consegue che un’istruzione non può avere alcun effetto in un programma quando crea un effetto collaterale, perché non può restituire un valore o restituisce solo il valore del tipo di Unità che è non assegnabile (in alcune lingue tali il void una C) o (come in Scala) possono essere memorizzati per una valutazione ritardata della dichiarazione.

Ovviamente un @pragma o un /*comment*/ non hanno alcun tipo e quindi sono differenziati dalle dichiarazioni. Quindi l’unico tipo di affermazione che non avrebbe effetti collaterali sarebbe una non operazione. La non-operazione è utile solo come segnaposto per effetti collaterali futuri. Qualsiasi altra azione dovuta a una dichiarazione sarebbe un effetto collaterale. Anche in questo caso un suggerimento del compilatore, ad esempio @pragma , non è un’istruzione perché non ha alcun tipo.

Più precisamente, una dichiarazione deve avere un “effetto collaterale” (cioè essere imperativo ) e un’espressione deve avere un tipo di valore (cioè non il tipo in basso).

Il tipo di un’istruzione è il tipo di unità, ma a causa dell’unità di teorizzazione di Halting è la fiction, quindi diciamo il tipo in basso .


Void non è precisamente il tipo di fondo (non è il sottotipo di tutti i tipi possibili). Esiste in lingue che non hanno un sistema di tipo completamente sano . Potrebbe sembrare un’affermazione snob, ma la completezza come le annotazioni sulla varianza sono fondamentali per scrivere software estensibile.

Vediamo cosa ha da dire Wikipedia su questo argomento.

https://en.wikipedia.org/wiki/Statement_(computer_science)

Nella programmazione per computer una dichiarazione è il più piccolo elemento autonomo di un linguaggio di programmazione imperativo che esprime un’azione da svolgere.

Molte lingue (ad es. C) distinguono tra istruzioni e definizioni, con un’istruzione che contiene solo codice eseguibile e una definizione che dichiara un identificatore, mentre un’espressione valuta solo un valore.