Espressione contro dichiarazione


432

Lo sto chiedendo per quanto riguarda c #, ma presumo che sia lo stesso nella maggior parte delle altre lingue.

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


4
Trovo che la risposta che hai scelto sia ambigua. Un'espressione fa anche qualcosa: valuta un valore. Ho fornito una risposta non ambigua.
Shelby Moore III,

4
@ShelbyMooreIII - Non ambiguo e anche sbagliato. La risposta accettata è formulata in modo informale, ma tale formulazione facilita la comprensione e, soprattutto, il significato che trasmette è accurato.
Justin Morgan,

@JustinMorgan Purtroppo, anche le definizioni nella risposta accettata sono ovviamente errate ("valuta un valore" / "una riga di codice") per la maggior parte dei linguaggi contemporanei includono quelli di tipo C: le espressioni possono essere utilizzate in contesti non valutati e le dichiarazioni non hanno nulla a che fare con le linee. Anche se ci sono alcune spiegazioni, la risposta breve è confusa e fuorviante.
FrankHB,

Risposte:


521

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

Nei primi linguaggi di programmazione per scopi generali, come FORTRAN, la distinzione era chiara. In FORTRAN, una dichiarazione era un'unità di esecuzione, una cosa che hai fatto. L'unico motivo per cui non era chiamata "linea" era perché a volte si estendeva su più linee. 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 è stata inventata, insieme a Backus-Naur Form (BNF), come parte della definizione di Algol-60. A quel punto la distinzione semantica ("avere un valore" rispetto a "fare qualcosa") era racchiusa nella sintassi : un tipo di frase era un'espressione e un altro era un'affermazione e il parser poteva distinguerli.

I progettisti delle lingue successive hanno offuscato la distinzione: hanno permesso alle espressioni sintattiche di fare le cose e hanno consentito dichiarazioni sintattiche che avevano valori. Il primo esempio di linguaggio popolare che sopravvive ancora è C. I progettisti di C si resero conto che nessun danno veniva fatto se ti fosse permesso di valutare un'espressione e buttare via il risultato. In C, ogni espressione sintattica può essere trasformata in una dichiarazione semplicemente virgolando un punto e virgola alla fine:

1 + 2 / x;

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

1 + 2 / callfunc(12);

perché callfuncpotrebbe semplicemente fare qualcosa di utile.

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

callfunc(x = 2);

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

Questa sfocatura delle espressioni e delle istruzioni si verifica in tutti i derivati ​​C (C, C ++, C # e Java), che hanno ancora alcune istruzioni (come while) ma che consentono a quasi tutte le espressioni di essere utilizzate come un'istruzione (nell'assegnazione solo C #, espressioni di chiamata, incremento e decremento possono essere usate come dichiarazioni; vedere la risposta di Scott Wisniewski ).

Avere due "categorie sintattiche" (che è il nome tecnico per il tipo di cose che sono le dichiarazioni e le espressioni) può portare alla duplicazione degli sforzi. Ad esempio, C ha due forme condizionali, la forma di istruzione

if (E) S1; else S2;

e la forma di espressione

E ? E1 : E2

E a volte le persone vogliono duplicazioni che non ci sono: nello standard C, ad esempio, solo un'istruzione può dichiarare una nuova variabile locale, ma questa capacità è abbastanza utile che il compilatore GNU C fornisce un'estensione GNU che consente a un'espressione di dichiarare un anche variabile locale.

Ai progettisti di altre lingue non piaceva questo tipo di duplicazione e hanno capito presto che se le espressioni possono avere effetti collaterali e valori, la distinzione sintattica tra affermazioni ed espressioni non è poi così utile, quindi si sono sbarazzati di esso . Haskell, Icon, Lisp e ML sono tutte lingue che non hanno dichiarazioni sintattiche - hanno solo espressioni. Persino il loop strutturato di classe e le forme condizionali sono considerate espressioni e hanno valori, ma non molto interessanti.


9
Se non ti sto interpretando male qui, sembri affermare che "(setf (terzo foo) 'oca)" è un'espressione, non un'affermazione, sia perché è Lisp, che "non ha dichiarazioni", e perché Lisp ha più di un decennio più di C, che era "il primo linguaggio popolare a confondere le linee [tra espressioni e dichiarazioni]". Potresti spiegarmi i dettagli di questo?
cjs,

2
@Curt Sampson, l'hai posto come domanda separata?
Kelly S. francese,

5
Se non sbaglio, callfunc(x = 2);passa xa callfunc, no 2. Se xè un float, callfunc(float)verrà chiamato, no callfunc(int). E in C ++, se passi x=ya func, e funcprende un riferimento e lo cambia x, cambia , no y.
Gabriel,

Nella risposta sopra, è scritto che "Haskell, ... sono tutte le lingue che non hanno dichiarazioni sintattiche - hanno solo espressioni". Sono curioso wheredi sapere perché la clausola in haskell sia considerata un'espressione e non un'affermazione. learnyouahaskell.com/syntax-in-functions#where
skgbanga

@skgbanga Credo che in whererealtà faccia parte della dichiarazione di funzione, non dell'espressione o dell'istruzione .
Akangka

22
  • un'espressione è tutto ciò che produce un valore: 2 + 2
  • un'istruzione è uno dei "blocchi" di base dell'esecuzione del programma.

Si noti che in C, "=" è in realtà un operatore, che fa due cose:

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

Ecco un estratto della grammatica ANSI C. Puoi vedere che C non ha molti diversi tipi di istruzioni ... la maggior parte delle istruzioni in un programma sono espressioni di espressione, 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


2
Logica errata su cosa sia un'istruzione. Un programma dichiarativo può anche essere eseguito, ma un programma dichiarativo non ha dichiarazioni. Un'affermazione è e fa "effetti collaterali" , cioè è indispensabile. cf. la mia risposta .
Shelby Moore III,

15

Un'espressione è qualcosa che restituisce un valore, mentre un'istruzione no.

Per esempio:

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

Il grosso problema tra i due è che puoi unire le espressioni insieme, mentre le affermazioni non possono essere concatenate.


6
Certe dichiarazioni possono essere concatenate. {stmt1; stmt2; stmt3;} è una catena ed è anche un'istruzione (composta) stessa.
Hugh Allen

5
foo.voidFunc(1);è un'espressione con un valore vuoto. whilee ifsono dichiarazioni.
tzot

Sono curioso di non concatenare le dichiarazioni. Qualcosa del tipo "if (x> 1) return;" essere considerato come concatenare due affermazioni insieme?
Simon Tewsi,

1
@SimonTewsi Credo che returnsia considerato un sostituto.
RastaJedi

1
@SimonTewsi L'istruzione return qui è implicitamente all'interno del blocco dell'istruzione if, quindi fa parte dell'istruzione if, non concatenata. Il compilatore ci consente di omettere le parentesi graffe, poiché si tratta di un blocco a riga singola.
user2597608

9

Puoi trovarlo su Wikipedia , ma le espressioni vengono valutate in base a un valore, mentre le istruzioni non hanno un valore valutato.

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

Nota che alcune lingue (come Lisp, e credo che Ruby, e molte altre) non differenziano l'affermazione rispetto all'espressione ... in tali lingue, tutto è un'espressione e può essere incatenato con altre espressioni.


8

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

I linguaggi imperativi (Fortran, C, Java, ...) enfatizzano le dichiarazioni 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 dichiarazioni possono essere eliminate del tutto.


5

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

Le espressioni di chiamate di funzione possono anche essere considerate istruzioni naturalmente, ma a meno che l'ambiente di esecuzione non abbia una speciale variabile incorporata per contenere il valore restituito, non c'è modo di recuperarlo.

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

Sebbene sia possibile comporre entrambi i tipi, la maggior parte delle espressioni può essere composta arbitrariamente purché i tipi corrispondano. Ogni tipo di affermazione ha il suo modo di comporre altre affermazioni, se possono fare tutto questo. Prevedere e se le istruzioni richiedono una singola istruzione o tutte le istruzioni subordinate vanno in un blocco di istruzioni, una dopo l'altra, a meno che i sottostati non consentano i propri sottostati.

Le dichiarazioni possono anche includere espressioni, in cui un'espressione in realtà non include alcuna istruzione. Un'eccezione, tuttavia, sarebbe un'espressione lambda, che rappresenta una funzione, e quindi può includere tutto ciò che una funzione può comprendere a meno che il linguaggio consenta solo lambda limitate, come le lambda ad espressione singola di Python.

In un linguaggio basato sulle espressioni, è sufficiente un'unica espressione per una funzione poiché tutte le strutture di controllo restituiscono un valore (molte restituiscono NIL). Non è necessaria un'istruzione return poiché l'ultima espressione valutata nella funzione è il valore restituito.


Il tipo di un'istruzione è il tipo in basso. Voidnon è il tipo in basso. Vedere la mia risposta .
Shelby Moore III,

1
Il tipo null non è il tipo inferiore (valore singolo di null)? Non voidsarebbe più simile al tipo di unità (ma con il suo valore singolo inaccessibile)?
Mark Cidade,

Se voidè il tipo restituito di una funzione che non ritorna mai (ad es. Una funzione che throwè un errore), è il tipo inferiore . Altrimenti voidè il tipo di unità . Hai ragione nel dire che un'istruzione che non può divergere ha il tipo di unità. Ma un'affermazione che può divergere è il tipo in basso. A causa del teorema di Halting, di solito non possiamo dimostrare che una funzione non diverge, quindi penso che l'unità sia finzione. Il tipo in basso non può avere un valore, quindi non può avere un singolo valore di null.
Shelby Moore III,

1
Per quanto riguarda quello che ho detto tre anni fa, non so se penso ancora che le dichiarazioni abbiano un tipo vuoto o qualsiasi tipo davvero. Nei linguaggi basati su istruzioni con cui ho familiarità, solo i valori e tutto ciò che memorizza o restituisce un valore (ad esempio espressioni, variabili, membri e funzioni) possono avere tipi. In genere penso al tipo inferiore come all'insieme vuoto (nessun valore) e quindi tutto ciò che non esiste ontologicamente avrebbe questo tipo. Un nullvalore è in realtà uno pseudovalue che indica che un riferimento si riferisce a qualcosa che non esiste.
Mark Cidade, il

1
Marco ho apprezzato la razionalità della tua risposta. Fondamentalmente mi hai tolto le parole dalla bocca e spero che fosse chiaro che ti avevo ammesso che avevi ragione nel sollevare il punto unitario. Penso che siamo d'accordo. Non mi preoccuperei di menzionarlo, ma sembra che alcune persone qui pensino che io sia negativo. Sto solo cercando di essere reale.
Shelby Moore III,

4

Semplicemente: un'espressione restituisce un valore, un'istruzione no.


Quindi cosa fa una dichiarazione? Niente?
Shelby Moore III,

1
Può fare qualcosa, ma non valuta nulla. Vale a dire, non è possibile assegnare il risultato di esso a una variabile, mentre è possibile con un'espressione.
Matthew Schinckel,

E quindi una dichiarazione deve avere effetti collaterali, come afferma la mia risposta fortemente votata verso il basso. Quale altra utilità potrebbe avere un'affermazione? Anche se un NO-OP fosse considerato un'affermazione (è solo un'affermazione in grammatica ma non a livello di semantica perché viene cancellata dopo l'analisi e la semantica è ciò di cui stiamo discutendo qui), non spiegherebbe ciò che il diamine l'utilità generale di una dichiarazione è.
Shelby Moore III,

1
Le dichiarazioni di @ShelbyMooreIII non devono fare nulla o avere effetti collaterali. ad esempio, {}è una dichiarazione. Mettere la parola tra virgolette non cambia questo. Le dichiarazioni sono costrutti sintattici con la semantica. Non esiste "il livello della semantica": sembra che tu ti riferisca all'esecuzione . Dici che stai cercando di essere preciso, ma non ci sei riuscito. La tua lamentela riguardo "l'ignoranza dei votanti" è pura pubblicità; non hai informazioni sugli stati mentali dei downvoter.
Jim Balter,

Sì, tutti hanno torto tranne il intellettualmente disonesto. {}è definito come un'istruzione nelle specifiche del linguaggio C #.
Jim Balter,

4

Alcune cose sui linguaggi basati sull'espressione:


Più importante: tutto restituisce un valore


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


In un linguaggio basato sull'espressione, tutto restituisce un valore. All'inizio può essere un po 'strano - Cosa (FOR i = 1 TO 10 DO (print i))ritorna?

Alcuni semplici esempi:

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

Un paio di esempi più complessi:

  • Alcune cose, come alcune chiamate di funzioni, non hanno davvero un valore significativo da restituire (Cose che producono solo effetti collaterali?). La chiamata OpenADoor(), FlushTheToilet()o TwiddleYourThumbs()restituirà una sorta di valore banale, come OK, Fine o Operazione riuscita.
  • 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 fare un esempio (FOR i = 1 TO 10 DO (print i)), il valore del ciclo for è "10", fa sì che l' (print i)espressione venga valutata 10 volte, ogni volta restituendo i come stringa. Il tempo finale attraverso i ritorni 10, la nostra risposta finale

Richiede spesso un leggero cambio di mentalità per ottenere il massimo da un linguaggio basato sull'espressione, poiché il fatto che tutto sia un'espressione rende possibile "incorporare" molte cose

A titolo di esempio:

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

è un sostituto perfettamente valido per i non basati 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 consente il codice basato su espressioni mi sembra molto più naturale

Certo, questo può portare alla follia. Come parte di un progetto hobby in un linguaggio di scripting basato sull'espressione chiamato MaxScript, sono riuscito a trovare questa linea mostruosa

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
)

2

Un'istruzione è un caso speciale di un'espressione, uno con voidtipo. La tendenza delle lingue a trattare le dichiarazioni in modo diverso spesso causa problemi e sarebbe meglio se fossero adeguatamente generalizzate.

Ad esempio, in C # abbiamo l'utilissimo Func<T1, T2, T3, TResult>set sovraccaricato di delegati generici. Ma dobbiamo anche disporre di un Action<T1, T2, T3>set corrispondente e la programmazione di ordine superiore per scopi generali deve essere costantemente duplicata per far fronte a questa sfortunata biforcazione.

Esempio di valutazione: una funzione che controlla se un riferimento è nullo prima di chiamare un'altra funzione:

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

Il compilatore potrebbe affrontare la possibilità di TResultessere void? Sì. Tutto ciò che deve fare è richiedere che return sia seguito da un'espressione di tipo void. Il risultato di default(void)sarebbe di tipo voide la funzione che passava dovrebbe essere nella forma Func<TValue, void>(che sarebbe equivalente a Action<TValue>).

Diverse altre risposte implicano che non puoi concatenare affermazioni come puoi con le espressioni, ma non sono sicuro da dove provenga questa idea. Possiamo pensare a quello ;che appare dopo le istruzioni come un operatore binario di infix, prendendo due espressioni di tipo voide combinandole in una singola espressione di tipo void.


Un'affermazione non è un caso speciale di espressione. In alcune lingue (cioè la maggior parte dei successori C), in realtà è il contrario.
Akangka

2

Istruzioni -> Istruzioni per seguire le
espressioni in sequenza -> Valutazione che restituisce un valore

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

Le espressioni non implicano e l'ordine di esecuzione a prima vista, il loro scopo è valutare e restituire un valore. Nei linguaggi di programmazione imperativa 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 riga (istruzione) di esecuzione su un'altra riga)

Esempio di espressioni:

2+2

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


Che dire degli effetti collaterali?
Austin Henley,

@AustinHenley non è necessario per questo. In effetti, un'espressione può sicuramente avere un effetto collaterale.
Akangka,

1

Dichiarazione ,

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

Una serie di affermazioni 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 # spesso contengono 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, oggetto, metodo o spazio dei nomi. I due tipi più semplici di espressioni sono letterali e nomi semplici. Un letterale è un valore costante che non ha nome.

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

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


Preferirei scrivere if(number >= 0) return true; else return false;o anche meglio bool? IsPositive(int number) { if(number > 0) return true; else if(number < 0) return false; else return null;}:)
Mahdi Tahsildari,

1

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

Immagino che ci sarà sempre confusione nel mondo dell'informatica e della scienza in generale quando vengono introdotte nuove terminologie o parole, le parole esistenti vengono "riproposte" o gli utenti ignorano la terminologia esistente, stabilita o "corretta" per ciò che stanno descrivendo


1

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 però più complicata).

Un'istruzione è composta da zero o più espressioni, ma può anche essere altri concetti linguistici. Questo è il modulo Extended Backus Naur per la grammatica (estratto per l'affermazione):

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 considerati dichiarazioni in C ++.

  • expression-statement s si spiega da sé (un'istruzione può essere composta da zero o più espressioni, leggere attentamente la grammatica, è complicata)
  • caseper esempio è un'istruzione con etichetta
  • le dichiarazioni di selezione sono if if/else,case
  • iterazione-dichiarazione s sono while, do...while,for (...)
  • jump-dichiarazione s sono break, continue, return(può tornare espressione),goto
  • dichiarazione-dichiarazione è l'insieme di dichiarazioni
  • try-block è un'istruzione che rappresenta i try/catchblocchi
  • e potrebbero essercene altri in grammatica

Questo è un estratto che mostra la parte delle 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 incarichi
  • condizionale-espressione (suoni ingannevole) si riferisce all'uso degli operatori ( +, -, *, /, &, |, &&, ||, ...)
  • espressione di lancio - eh? anche la throwclausola è un'espressione

0

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

x = 5

legge "x ottiene 5." Questa è una frase completa Il codice

(x + 5)/9.0

dice "x più 5 tutti divisi 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.


whileè un'espressione è alcune lingue come Scala. Stai mescolando la grammatica con la digitazione. Vedere la mia risposta .
Shelby Moore III,

Ecco il ciclo while in scala: tutorialspoint.com/scala/scala_while_loop.htm Il ciclo con il suo predicato e nessun corpo non è una frase grammaticalmente completa. Non è un'espressione completa. Hai bisogno del corpo per completarlo come espressione.
ncmathsadist

A whilecon un corpo è ancora un'espressione in Scala. Può anche essere un'affermazione se crea effetti collaterali, cosa che consente la mia risposta fortemente declassata (un'espressione può anche essere un'affermazione). La mia risposta è l'unica corretta. Mi dispiace per tutti quei lettori che non riescono a capire.
Shelby Moore III,

Cosa intendi per grammaticalmente completo? In C, (x + 5)/9.0può sicuramente essere solo come una dichiarazione. Inoltre, se per grammaticalmente completo si intende un programma valido, C non consente alle istruzioni di essere considerate singole come un singolo programma.
Akangka,

Grammaticamente completo: costituisce una frase completa.
ncmathsadist,

0

Ecco la sintesi di una delle risposte più semplici che ho trovato.

originariamente risposto da Anders Kaseorg

Un'istruzione è una riga di codice completa che esegue alcune azioni, mentre un'espressione è qualsiasi sezione del codice che restituisce un valore.

Le espressioni possono essere combinate "orizzontalmente" in espressioni più grandi utilizzando gli operatori, mentre le istruzioni possono essere combinate "verticalmente" solo scrivendo una dopo l'altra o con costrutti di blocco.

Ogni espressione può essere utilizzata come un'istruzione (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


0

La base di fatto di questi concetti è:

Espressioni : una categoria sintattica la cui istanza può essere valutata su un valore.

Dichiarazione : una categoria sintattica la cui istanza può essere coinvolta con le valutazioni di un'espressione e il valore risultante della valutazione (se presente) non è garantita disponibile.

Oltre al contesto iniziale di FORTRAN nei primi decenni, entrambe le definizioni di espressioni e dichiarazioni nella risposta accettata sono ovviamente sbagliate:

  • Le espressioni possono essere operandi non valutati. I valori non vengono mai prodotti da loro.
    • Le sottoespressioni nelle valutazioni non rigorose possono essere sicuramente non valutate.
      • La maggior parte dei linguaggi di tipo C hanno le cosiddette regole di valutazione del corto circuito per saltare condizionatamente alcune valutazioni di sottoespressione e non modificare il risultato finale nonostante gli effetti collaterali.
    • C e alcuni linguaggi di tipo C hanno la nozione di operando non valutato che può anche essere normalmente definito nella specifica del linguaggio. Tali costrutti sono usati per evitare definitivamente le valutazioni, quindi le informazioni sul contesto rimasto (ad es. Tipi o requisiti di allineamento) possono essere distinte staticamente senza cambiare il comportamento dopo la traduzione del programma.
      • Ad esempio, un'espressione utilizzata come operando sizeofdell'operatore non viene mai valutata.
  • Le dichiarazioni non hanno nulla a che fare con i costrutti di linea. Possono fare qualcosa di più delle espressioni, a seconda delle specifiche della lingua.
    • Il moderno Fortran, come discendente diretto del vecchio FORTRAN, ha concetti di istruzioni eseguibili e di istruzioni non eseguibili .
    • Analogamente, C ++ definisce le dichiarazioni come la sottocategoria di livello superiore di un'unità di traduzione. Una dichiarazione in C ++ è una dichiarazione. (Questo non è vero in C.) Esistono anche espressioni di espressione come le dichiarazioni eseguibili di Fortran.
    • Per l'interesse del confronto con le espressioni, contano solo le dichiarazioni "eseguibili". Ma non si può ignorare il fatto che le dichiarazioni sono già generalizzate come costrutti che formano le unità di traduzione in tali linguaggi imperativi. Quindi, come puoi vedere, le definizioni della categoria variano molto. La (probabilmente) proprietà comune rimasta solo tra queste lingue è che le dichiarazioni dovrebbero essere interpretate nell'ordine lessicale (per la maggior parte degli utenti, da sinistra a destra e dall'alto verso il basso).

(A proposito, voglio aggiungere [citazione necessaria] a quella risposta riguardante i materiali su C perché non riesco a ricordare se DMR abbia tali opinioni. Sembra di no, altrimenti non dovrebbero esserci motivi per preservare la duplicazione della funzionalità nella progettazione di C : in particolare, l'operatore virgola rispetto alle istruzioni.)

(La seguente logica non è la risposta diretta alla domanda originale, ma ritengo necessario chiarire qualcosa che ha già risposto qui.)

Tuttavia, è dubbio che sia necessaria una categoria specifica di "dichiarazioni" nei linguaggi di programmazione generici:

  • Non è garantito che le dichiarazioni abbiano più capacità semantiche rispetto alle espressioni nei normali progetti.
    • Molte lingue hanno già abbandonato con successo la nozione di dichiarazioni per ottenere progetti globali puliti, ordinati e coerenti.
      • In tali linguaggi, le espressioni possono fare tutto ciò che possono fare le affermazioni di vecchio stile: rilasciare i risultati non utilizzati quando vengono valutate le espressioni, lasciando i risultati esplicitamente non specificati (ad es. Nello schema R n RS) o avendo un valore speciale (come valore di un tipo di unità) non producibile dalle valutazioni delle espressioni normali.
      • Le regole di ordine lessicale di valutazione delle espressioni possono essere sostituite da un operatore di controllo di sequenza esplicito (ad esempio beginnello Schema) o da zucchero sintattico di strutture monadiche.
      • Le regole di ordine lessicale di altri tipi di "istruzioni" possono essere derivate come estensioni sintattiche (usando macro igieniche, per esempio) per ottenere la stessa funzionalità sintattica. (E in realtà può fare di più .)
    • Al contrario, le dichiarazioni non possono avere regole così convenzionali, perché non si basano sulla valutazione: non esiste proprio una nozione così comune di "valutazione dei sottostati". (Anche se ce ne sono, dubito che ci possa essere qualcosa di molto più di un semplice copia e incolla dalle regole di valutazione delle espressioni esistenti).
      • In genere, le istruzioni che preservano le lingue avranno anche espressioni per esprimere i calcoli e esiste una sottocategoria di livello superiore delle istruzioni conservate nelle valutazioni delle espressioni per quella sottocategoria. Ad esempio, C ++ ha la cosiddetta dichiarazione-espressione come sottocategoria e utilizza le regole di valutazione delle espressioni con valore scartato per specificare i casi generali di valutazioni di espressioni complete in tale contesto. Alcuni linguaggi come C # scelgono di affinare i contesti per semplificare i casi d'uso, ma gonfia di più le specifiche.
  • Per gli utenti dei linguaggi di programmazione, il significato delle dichiarazioni può confonderle ulteriormente.
    • La separazione delle regole delle espressioni e delle dichiarazioni nelle lingue richiede uno sforzo maggiore per imparare una lingua.
    • L'ingenua interpretazione dell'ordine lessicale nasconde la nozione più importante: la valutazione dell'espressione. (Questo è probabilmente il più problematico in assoluto.)
      • Anche le valutazioni delle espressioni complete nelle istruzioni sono vincolate all'ordine lessicale, le sottoespressioni non lo sono (necessariamente). Gli utenti dovrebbero in definitiva apprenderlo oltre a qualsiasi regola associata alle dichiarazioni. (Considera come fare in modo che un principiante ottenga il punto che non ha ++i + ++isenso in C.)
      • Alcuni linguaggi come Java e C # vincolano ulteriormente l'ordine delle valutazioni delle sottoespressioni a consentire l'ignoranza delle regole di valutazione. Può essere ancora più problematico.
        • Ciò sembra eccessivamente specificato per gli utenti che hanno già imparato l'idea della valutazione delle espressioni. Incoraggia anche la comunità di utenti a seguire il modello mentale offuscato del design del linguaggio.
        • Aumenta ulteriormente le specifiche del linguaggio.
        • È dannoso per l'ottimizzazione mancando l'espressività del non determinismo nelle valutazioni, prima che vengano introdotte primitive più complicate.
      • Alcuni linguaggi come C ++ (in particolare, C ++ 17) specificano contesti più sottili delle regole di valutazione, come un compromesso dei problemi di cui sopra.
        • Gonfia molto le specifiche del linguaggio.
        • Questo è totalmente contrario alla semplicità per gli utenti medi ...

Quindi perché le dichiarazioni? Comunque, la storia è già un casino. Sembra che la maggior parte dei progettisti di lingue non faccia la loro scelta con attenzione.

Peggio ancora, fornisce anche ad alcuni appassionati di sistemi di tipo (che non hanno abbastanza familiarità con la storia di PL) alcune idee sbagliate secondo cui i sistemi di tipo devono avere cose importanti da fare con i disegni più essenziali delle regole sulla semantica operativa.

Scherzi a parte, il ragionamento a seconda dei tipi non è poi così male in molti casi, ma soprattutto non costruttivo in questo speciale. Anche gli esperti possono rovinare tutto.

Ad esempio, qualcuno sottolinea la natura ben tipizzante come argomento centrale contro il trattamento tradizionale di continuazioni non delimitate . Sebbene la conclusione sia alquanto ragionevole e le intuizioni sulle funzioni composte siano OK ( ma ancora troppo ingenue per l'essenza ), questo argomento non è valido perché ignora totalmente l'approccio del "canale laterale" in pratica come _Noreturn any_of_returnable_types(in C11) per codificare Falsum. E a rigor di termini, una macchina astratta con uno stato imprevedibile non è identica a "un computer bloccato".


0

In un linguaggio di programmazione orientato alle istruzioni, un blocco di codice è definito come un elenco di istruzioni. In altre parole, un'istruzione è una parte della sintassi che è possibile inserire in un blocco di codice senza causare un errore di sintassi.

Wikipedia definisce la frase in modo simile

Nella programmazione informatica, un'affermazione è un'unità sintattica di un linguaggio di programmazione imperativo che esprime alcune azioni da svolgere. Un programma scritto in tale linguaggio è formato da una sequenza di una o più istruzioni

Nota quest'ultima affermazione. (anche se "un programma" in questo caso è tecnicamente errato perché sia ​​C che Java rifiutano un programma che non consiste in nulla di dichiarazioni.)

Wikipedia definisce la parola espressione come

Un'espressione in un linguaggio di programmazione è un'entità sintattica che può essere valutata per determinarne il valore

Questo, tuttavia, è falso, perché in Kotlin throw new Exception("")è un'espressione ma, quando valutato, genera semplicemente un'eccezione, senza mai restituire alcun valore.

In un linguaggio di programmazione tipicamente statico, ogni espressione ha un tipo. Questa definizione, tuttavia, non funziona in un linguaggio di programmazione tipizzato in modo dinamico.

Personalmente, definisco un'espressione come un pezzo di sintassi che può essere composto con un operatore o chiamate di funzione per produrre un'espressione più grande. Questo è in realtà simile alla spiegazione dell'espressione di Wikipedia:

È una combinazione di una o più costanti, variabili, funzioni e operatori che il linguaggio di programmazione interpreta (secondo le sue particolari regole di precedenza e di associazione) e calcola per produrre ("restituire", in un ambiente con stato) un altro valore

Ma il problema è nel linguaggio di programmazione C, data una funzione execute Qualcosa del genere:

void executeSomething(void){
    return;
}

È executeSomething()un'espressione o è un'affermazione? Secondo la mia definizione, è un'affermazione perché, come definito nella grammatica di riferimento C di Microsoft,

Non è possibile utilizzare il valore (inesistente) di un'espressione che ha tipo void in alcun modo, né è possibile convertire un'espressione void (mediante conversione implicita o esplicita) in qualsiasi tipo tranne void

Ma la stessa pagina indica chiaramente che tale sintassi è un'espressione.


-6

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

Un'espressione ha un tipo diverso dal tipo Bottom, ovvero ha un valore. Un'istruzione ha il tipo Unità o In basso.

Da ciò ne consegue che un'istruzione può avere alcun effetto in un programma solo 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 una C void) o (come in Scala) possono essere archiviati per una valutazione ritardata della dichiarazione.

Ovviamente a @pragmao a /*comment*/non hanno tipo e quindi sono differenziati dalle dichiarazioni. Pertanto, l'unico tipo di affermazione che non avrebbe effetti collaterali sarebbe una non-operazione. La non operatività è 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 tipo.


2
La distinzione non ha nulla a che fare con il tipo di espressioni. Le istruzioni definite sintatticamente non hanno alcun tipo in molte lingue. Anche se non sono contrario ad assegnare un tipo a tali termini in teoria, trattamenti diversi su @pragmao /*comment*/sono logicamente incoerenti.
FrankHB,

-11

Più precisamente, un'istruzione deve avere un "effetto collaterale" (cioè essere un imperativo ) e un'espressione deve avere un tipo di valore (cioè non il tipo inferiore).

Il tipo di un'istruzione è il tipo di unità, ma a causa del teorema di Halting l'unità è finzione, quindi diciamo il tipo di fondo .


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

Vediamo cosa ha da dire Wikipedia in merito.

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

Nella programmazione per computer un'affermazione è il più piccolo elemento autonomo di un linguaggio di programmazione imperativo che esprime alcune azioni da svolgere.

Molte lingue (ad es. C) fanno una distinzione tra istruzioni e definizioni, con un'istruzione contenente solo codice eseguibile e una definizione che dichiara un identificatore, mentre un'espressione restituisce solo un valore.


5
Una dichiarazione non deve avere effetti collaterali. Ad esempio, in Python passè una dichiarazione. È una no-op e non valuta nulla.
Matthew Schinckel,

9
-1 Questo è sbagliato. Una dichiarazione non deve avere un effetto collaterale. Vedere la sezione 1.5 della specifica del linguaggio C # . Non solo non specificare che le dichiarazioni devono avere effetti collaterali, ma elenca anche diverse dichiarazioni che possono avere alcun effetto collaterale.
NullUserException il

2
@NullUserException Ho letto quella sezione. Le dichiarazioni Dichiarazione, Espressione, Selezione, Iterazione e Salto possono creare effetti collaterali. Ma se esiste un'espressione RT, allora non è un'affermazione. Mi rendo conto che la specifica sta equiparando le espressioni alle dichiarazioni, ma questa domanda ha chiesto la differenza tra loro. Quindi o la domanda non ha risposta, o stai prendendo le specifiche C # troppo alla lettera. La risposta più votata è cercare di dire quello che ho fatto. Ma "fa qualcosa" non ha senso. "effetto collaterale" è il modo significativo di dire "fa qualcosa". Dobbiamo pensare, non solo rigurgitare.
Shelby Moore III,

13
@ShelbyMooreIII Hai ragione. La documentazione ufficiale è errata . Marc Gravell e Jon Skeet, che sono probabilmente i più rispettati poster C # attivi su SO al di fuori di Eric Lippert, hanno torto . Io e tutti gli altri che ti hanno votato per difetto e lasciato commenti che spiegano la nostra posizione sono sbagliati . Hai ragione. Sei chiaramente l'unica persona che sa di cosa stanno parlando, dato che sei molto più intelligente di tutto il resto della SO.
NullUserException,

3
Conoscere la definizione precisa di concetti come affermazione, espressione, cast, conversione ecc. Non ha alcun impatto sul 99,999% delle attività di programmazione quotidiane. Pensate che . Inoltre: alla maggior parte delle persone non importa di Haskell e Scala.
NullUserException
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.