Perché il tipo va dopo il nome della variabile nei moderni linguaggi di programmazione?

38

Perché in quasi tutti i linguaggi di programmazione moderni (Go, Rust, Kotlin, Swift, Scala, Nim, persino Python dell'ultima versione) i tipi vengono sempre dopo il nome della variabile nella dichiarazione delle variabili, e non prima?

Perché x: int = 42 e non int x = 42 ?
Quest'ultimo non è più leggibile rispetto al precedente?
E 'solo una tendenza o ci sono ragioni davvero significative dietro questa soluzione?

    
posta Andre Polykanine 19.04.2016 - 20:39
fonte

4 risposte

48

Tutte le lingue che hai citato supportano inferenza del tipo , che significa il tipo è una parte facoltativa della dichiarazione in quelle lingue perché sono abbastanza intelligenti da riempirlo di per sé quando fornisci un'espressione di inizializzazione con un tipo facilmente determinabile.

Questo è importante perché mettere le parti facoltative di un'espressione più a destra riduce l'ambiguità del parsing e aumenta la coerenza tra le espressioni che usano quella parte e quelle che non lo fanno. È più semplice analizzare una dichiarazione quando sai che la parola chiave var e il nome della variabile sono entrambi obbligatori prima di arrivare alle cose facoltative. In teoria, tutte quelle cose che semplificano l'analisi dei computer dovrebbero migliorare la leggibilità complessiva anche per gli umani, ma è molto più discutibile.

Questo argomento diventa particolarmente strong se si considerano tutti i modificatori di tipo facoltativi che ha un linguaggio "non moderno" come C ++, come * per i puntatori, & per riferimenti, const , volatile e presto. Una volta che inserisci le virgole per più dichiarazioni, inizi a ottenere alcune ambiguità davvero strane come int* a, b; che non crea b un puntatore.

Anche C ++ ora supporta le dichiarazioni "type on the right" sotto forma di auto x = int{ 4 }; e ha alcuni vantaggi .

    
risposta data 19.04.2016 - 20:53
fonte
23

Why in nearly all modern programming languages (Go, Rust, Kotlin, Swift, Scala, Nim, even Python last version) types always come after the variable declaration, and not before?

La tua premessa è imperfetta su due fronti:

  • Esistono nuovi linguaggi di programmazione che hanno il tipo prima l'identificatore. C♯, D, o Ceylon, per esempio.
  • Avere il tipo dopo l'identificatore non è un fenomeno nuovo, risale almeno a Pascal (progettato nel 1968-1969, pubblicato nel 1970), ma in realtà è stato usato nella teoria dei tipi matematici, che inizia nel 1902. Fu usato anche in ML (1973), CLU (1974), Hope (1970), Modula-2 (1977-1985), Ada (1980), Miranda (1985), Caml (1985), Eiffel (1985), Oberon (1986), Modula-3 (1986-1988) e Haskell (1989).

Pascal, ML, CLU, Modula-2 e Miranda erano tutti lingue molto influenti, quindi non sorprende che questo tipo di dichiarazioni di tipo sia rimasto popolare.

Why x: int = 42 and not int x = 42? Is the latter not more readable than the former?

La leggibilità è una questione di familiarità. Personalmente, trovo che i cinesi siano illeggibili, ma a quanto pare, i cinesi non lo fanno. Avendo imparato Pascal a scuola, dilettandomi con Eiffel, F♯, Haskell e Scala, e avendo osservato TypeScript, Fortress, Go, Rust, Kotlin, Idris, Frege, Agda, ML, Ocaml, ..., mi sembra del tutto naturale .

Is it just a trend or are there any really meaningful reasons behind such a solution?

Se si tratta di una tendenza, è piuttosto persistente: come ho detto, risale a cento anni in matematica.

Uno dei principali vantaggi di avere il tipo dopo l'identificatore è che è facile lasciare il tipo se vuoi che venga dedotto. Se le tue dichiarazioni sono così:

val i: Int = 10

Quindi è banale tralasciare il tipo e dedurre in questo modo:

val i = 10

Se invece il tipo precede l'identificatore in questo modo:

Int i = 10

Quindi inizia a diventare difficile per il parser distinguere un'espressione da una dichiarazione:

i = 10

La soluzione che i progettisti linguistici di solito escogitano è di introdurre una parola chiave "Non voglio scrivere un tipo" che deve essere scritta al posto del tipo:

var  i = 10; // C♯
auto i = 10; // C++

Ma in realtà non ha molto senso: in pratica devi scrivere esplicitamente un tipo che dice che non scrivi un tipo. Eh? Sarebbe molto più semplice e sensato lasciarlo fuori, ma questo rende la grammatica molto più complessa.

(E non parliamo nemmeno dei tipi di puntatore a funzione in C.)

I progettisti di alcune delle suddette lingue hanno affrontato questo argomento:

  • Domande frequenti (vedi anche: Sintassi della dichiarazione di go ):

    Why are declarations backwards?

    They're only backwards if you're used to C. In C, the notion is that a variable is declared like an expression denoting its type, which is a nice idea, but the type and expression grammars don't mix very well and the results can be confusing; consider function pointers. Go mostly separates expression and type syntax and that simplifies things (using prefix * for pointers is an exception that proves the rule). In C, the declaration

    int* a, b;
    

    declares a to be a pointer but not b; in Go

    var a, b *int
    

    declares both to be pointers. This is clearer and more regular. Also, the := short declaration form argues that a full variable declaration should present the same order as := so

    var a uint64 = 1
    

    has the same effect as

    a := uint64(1)
    

    Parsing is also simplified by having a distinct grammar for types that is not just the expression grammar; keywords such as func and chan keep things clear.

  • Domande frequenti su Kotlin :

    Why have type declarations on the right?

    We believe it makes the code more readable. Besides, it enables some nice syntactic features. For instance, it is easy to leave type annotations out. Scala has also proven pretty well this is not a problem.

  • Programmazione in Scala :

    The major deviation from Java concerns the syntax for type annotations—it's "variable: Type" instead of "Type variable" in Java. Scala's postfix type syntax resembles Pascal, Modula-2, or Eiffel. The main reason for this deviation has to do with type inference, which often lets you omit the type of a variable or the return type of a method. Using the "variable: Type" syntax this is easy—just leave out the colon and the type. But in C-style "Type variable" syntax you cannot simply leave off the type—there would be no marker to start the definition anymore. You'd need some alternative keyword to be a placeholder for a missing type (C♯ 3.0, which does some type inference, uses var for this purpose). Such an alternative keyword feels more ad-hoc and less regular than Scala's approach.

Nota: i progettisti di Ceylon hanno anche documentato il motivo per cui usano la sintassi del tipo di prefisso :

Prefix instead of postfix type annotations

Why do you follow C and Java in putting type annotations first, instead of Pascal and ML in putting them after the declaration name?

     

Perché pensiamo che questo:

shared Float e = ....
shared Float log(Float b, Float x) { ... }
     

È molto più facile leggere di questo:

shared value e: Float = .... 
shared function log(b: Float, x: Float): Float { ... }
     

E semplicemente non capiamo come qualcuno possa pensare altrimenti!

Personalmente, trovo che il loro "argomento" sia molto meno convincente degli altri.

    
risposta data 20.04.2016 - 03:19
fonte
2

Anche Pascal lo fa a proposito, e non è una nuova lingua. Era comunque un linguaggio accademico, progettato da zero.

Direi che è semanticamente più chiaro per iniziare con il nome della variabile. Il tipo è solo un dettaglio tecnico. Se vuoi leggere la tua classe come il modello della realtà che è, ha senso mettere prima i nomi delle tue entità e la loro implementazione tecnica.

C # e java derivano da C così dovettero rispettare la "prior art", quindi non confondere il programmatore esperto.

    
risposta data 19.04.2016 - 20:57
fonte
1

Why x: int = 42 and not int x = 42? Is the latter not more readable than the former?

In un esempio così semplice, non c'è molta differenza, ma rendiamola un po 'più complessa: int* a, b;

Questa è una dichiarazione valida e valida in C, ma non fa quello che dovrebbe sembrare intuitivamente. Sembra che dichiariamo due variabili di tipo int* , ma in realtà dichiariamo una int* e una int .

Se la tua lingua inserisce il tipo dopo i nomi delle variabili nelle sue dichiarazioni, è impossibile eseguire questo problema.

    
risposta data 19.04.2016 - 20:45
fonte

Leggi altre domande sui tag