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?
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?
Risposte:
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é callfunc
potrebbe 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.
callfunc(x = 2);
passa x
a callfunc
, no 2
. Se x
è un float, callfunc(float)
verrà chiamato, no callfunc(int)
. E in C ++, se passi x=y
a func
, e func
prende un riferimento e lo cambia x
, cambia , no y
.
where
di sapere perché la clausola in haskell sia considerata un'espressione e non un'affermazione. learnyouahaskell.com/syntax-in-functions#where
where
realtà faccia parte della dichiarazione di funzione, non dell'espressione o dell'istruzione .
Si noti che in C, "=" è in realtà un operatore, che fa due cose:
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 ';'
;
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.
foo.voidFunc(1);
è un'espressione con un valore vuoto. while
e if
sono dichiarazioni.
return
sia considerato un sostituto.
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.
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.
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.
Void
non è il tipo in basso. Vedere la mia risposta .
null
)? Non void
sarebbe più simile al tipo di unità (ma con il suo valore singolo inaccessibile)?
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
.
null
valore è in realtà uno pseudovalue che indica che un riferimento si riferisce a qualcosa che non esiste.
Semplicemente: un'espressione restituisce un valore, un'istruzione no.
{}
è 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.
{}
è definito come un'istruzione nelle specifiche del linguaggio C #.
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:
OpenADoor(), FlushTheToilet()
o TwiddleYourThumbs()
restituirà una sorta di valore banale, come OK, Fine o Operazione riuscita.(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 finaleRichiede 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
)
Un'istruzione è un caso speciale di un'espressione, uno con void
tipo. 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 TResult
essere 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 void
e 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 void
e combinandole in una singola espressione di tipo void
.
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)
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.
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.
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;}
:)
Preferisco il significato statement
nel 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
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 ++.
case
per esempio è un'istruzione con etichettaif
if/else
,case
while
, do...while
,for (...)
break
, continue
, return
(può tornare espressione),goto
try/catch
blocchiQuesto è 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
+
, -
, *
, /
, &
, |
, &&
, ||
, ...)throw
clausola è un'espressioneLe 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 .
while
con 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.
(x + 5)/9.0
può 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.
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.
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:
sizeof
dell'operatore non viene mai valutata.(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:
begin
nello Schema) o da zucchero sintattico di strutture monadiche.++i + ++i
senso in C.)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".
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.
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 @pragma
o 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.
@pragma
o /*comment*/
sono logicamente incoerenti.
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 .
Void
non è 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.
pass
è una dichiarazione. È una no-op e non valuta nulla.