Quale espressività utile sarà impossibile in una lingua in cui un'espressione non è un'affermazione?

7

Sto pensando di scrivere un linguaggio di programmazione. La maggior parte delle grammatiche definisce le espressioni come una sorta di affermazione. Ma in realtà non riesco a trovare un singolo esempio di qualsiasi espressione utile che passerebbe come una dichiarazione.

Vedi link per una facile definizione di espressione vs dichiarazione.

EDIT: Perché ci sono così tante grammatiche che fanno la distinzione tra expr e stmt quando, come indicato nelle risposte, non ha senso.

    
posta Carlo V. Dango 12.08.2012 - 18:46
fonte

4 risposte

3

Una chiamata a una funzione / metodo è, ovviamente, un'espressione. Allo stesso tempo (in linguaggi di programmazione imperativi, che presumo dal momento che sembra dare per scontate le affermazioni) molte funzioni hanno effetti collaterali e quegli effetti collaterali sono spesso abbastanza incentivi per chiamare la funzione. Prendi in considerazione funzioni come printf che esistono principalmente per il loro effetto collaterale e il cui valore di ritorno (in questo caso, il numero di caratteri stampati) di solito non è interessante. O fondamentalmente qualsiasi funzione / metodo senza alcun valore di ritorno interessante - cioè void o () AKA unit . (Sebbene sia possibile, in un'impostazione tipizzata staticamente, distinguere tra i due, farlo è del tutto inutile.)

Nelle lingue con overloading dell'operatore, questo si estende a qualsiasi espressione che coinvolga operatori (leggi: quasi tutte le espressioni), perché queste sono fondamentalmente funzioni come sopra, chiamate solo in modo diverso. A volte una cattiva idea, sì, ma poi ci sono i DSL incorporati.

Inoltre, se assegni un'espressione (cattiva idea IMHO, ma piuttosto comune), praticamente hai bisogno di essere valida come affermazione. Idem per pre e post-incremento e -decrement - queste sono espressioni, ma per lo più utili come dichiarazioni indipendenti.

EDIT: Per quanto riguarda il motivo per cui la distinzione esiste: le istruzioni sono distinte dall'espressione, quindi la grammatica può impedire che le istruzioni vengano utilizzate come espressioni. Un esempio in Python: "espressione"

f(def g():
    pass
)

ha più problemi (in primo luogo: non funziona con il - altrimenti grande e semplice - il modo in cui viene gestita l'indentazione, può essere facilmente trasformato in una definizione di funzione interiore) che lo rendono assolutamente inutile. Per il confronto, def g(): pass; f(g) è perfettamente valido e talvolta (se f vuole un callback e vuoi un no-op per quello) utile. E non tutte le lingue accettano l'espressione ogni come dichiarazione - molte escludono alternative che mai hanno senso (cfr Pascal, C #), o danno un avvertimento ("la dichiarazione ha nessun effetto ").

    
risposta data 12.08.2012 - 19:06
fonte
3

"Quale espressività utile sarà impossibile in una lingua in cui un'espressione non è una dichiarazione?"

Nessuno.

Le definizioni di "espressione" e "affermazione" sono in gran parte arbitrarie. Diverse lingue li definiscono in modo diverso. Non conosco alcun linguaggio di programmazione il cui modo di definire questi termini renda ogni particolare impossibile da esprimere. In alcune lingue, alcuni costrutti potrebbero essere un po 'più scomodi; in altri, potrebbe essere più semplice scrivere codice difficile da leggere perché una singola istruzione dipende da più effetti collaterali.

Quasi tutti i linguaggi di programmazione sono Turing-complete e sono in grado di esprimere gli stessi comportamenti di qualsiasi altra lingua completa di Turing .

Due buoni esempi sono Pascal e C.

In Pascal, un compito è un'affermazione, non un'espressione. Una subroutine può essere una procedura (che non restituisce un valore) o una funzione (che lo fa). Una chiamata di procedura è un'istruzione e non può far parte di un'espressione. Una chiamata di funzione è un'espressione e non può apparire in un'istruzione se non si fa esplicitamente qualcosa con il risultato, ad esempio assegnandolo a una variabile. Le dichiarazioni possono contenere espressioni, ma le espressioni non possono contenere dichiarazioni.

In C, un compito è un'espressione. Tutte le subroutine sono funzioni; le funzioni che non restituiscono alcun valore sono dichiarate con un tipo di ritorno di void . Una chiamata di funzione è un'espressione; può essere trasformato in una dichiarazione aggiungendo un punto e virgola. Il risultato di una chiamata di funzione o di qualsiasi espressione può essere scartato in modo silenzioso. Qualsiasi espressione può essere trasformata in una dichiarazione aggiungendo un punto e virgola. Come in Pascal, le istruzioni possono contenere espressioni, ma le espressioni non possono contenere istruzioni (ma gcc fornisce espressioni di istruzioni come estensione di lingua).

Ecco un tipico costrutto C che dipende dalla capacità di trattare i compiti come espressioni ( item è un tipo arbitrario e last_item è una costante di quel tipo):

item x;
while ((x = get_next_item()) != last_item) {
    do_something_with(x);
}

In Pascal, puoi implementare esattamente lo stesso comportamento come questo (se ricordo correttamente la sintassi):

var
    x: item;
    done: boolean = false;
begin
    while not done do
    begin
        x := Next_Item;
        if x = last_item then
            done := true
        else
            do_something_with(x);
    end;
end;
    
risposta data 12.08.2012 - 22:02
fonte
1

Se fai riferimento alle definizioni fornite su quelle pagine, è facile capire perché è difficile trovare un'espressione che sarebbe passata come una dichiarazione.

Expression: Something which evaluates to a value. Example: 1+2/x

Statement: A line of code which does something. Example: GOTO 100

L'espressione è solo l'oggetto della dichiarazione. Se non lo assegni a qualcosa, alla fine, non c'è molto che tu possa fare con esso.

Potresti comunque voler esaminare il lisp.

    
risposta data 12.08.2012 - 19:13
fonte
0

Cose come la tradizionale chiamata send per socket è un buon esempio:

int send(int socket, char* buffer, int flags);

Il ritorno 'byte inviati' non è strettamente vitale per la funzione di fare la sua attività.

Potresti ovviamente dire che non controllare i byte inviati è un errore e che la tua lingua non dovrebbe permetterlo come input. Il problema deriva dal fatto che l'analisi viene eseguita prima che i tipi siano mai noti. Durante l'analisi

send( socket, buffer, 0 );

il tuo compilatore ha nessuna idea se send restituisce un valore o meno. Nella maggior parte delle lingue, è auspicabile che questa semplice espressione autonoma sia ammessa come una dichiarazione.

    
risposta data 12.08.2012 - 20:10
fonte

Leggi altre domande sui tag