Suggerirei che un buon linguaggio di programmazione dovrebbe avere regole rigide, che le implementazioni dovrebbero applicare in modo coerente, ma le regole dovrebbero essere scritte in modo tale da essere utili. Vorrei inoltre suggerire che si dovrebbe prendere in considerazione la progettazione di una lingua per evitare casi in cui la "distanza di Hamming" tra due programmi sostanzialmente diversi è solo uno. Ovviamente non si può ottenere una cosa del genere con letterali numerici o stringhe (se un programmatore che intendeva 123 invece digiti 1223 o 13, il compilatore non può sapere molto bene cosa intendesse il programma). D'altra parte, se il linguaggio dovesse usare :=
per l'assegnazione e ==
per il confronto di uguaglianza, e non usare un solo =
per qualsiasi scopo legale, ridurrebbe notevolmente le possibilità sia per gli incarichi accidentali che si supponeva che essere paragoni e paragoni casuali che non dovevano essere assegnati.
Suggerirei che mentre ci sono luoghi in cui è utile per i compilatori inferire le cose, tale inferenza è spesso più preziosa nei casi più semplici e meno valida nei casi più complicati. Ad esempio, consentendo la sostituzione di:
Dictionary<complicatedType1,complicatedType2> item =
new Dictionary<complicatedType1, complicatedType2()>;
con
var item = new Dictionary<complicatedType1, complicatedType2()>;
non richiede alcuna inferenza di tipo complicata, ma rende il codice molto più leggibile (tra l'altro, utilizza la sintassi più dettagliata solo negli scenari in cui è necessario, ad esempio perché il tipo di posizione di archiviazione non corrisponde esattamente al tipo l'espressione che la crea, ti aiuterà a prestare maggiore attenzione ai luoghi che potrebbero averne bisogno).
Una delle maggiori difficoltà nel tentare un'inferenza più sofisticata è che possono sorgere situazioni ambigue; Suggerirei che un buon linguaggio dovrebbe consentire a un programmatore di includere informazioni che il compilatore potrebbe utilizzare per risolvere tali ambiguità (ad esempio considerando alcune tipizzazioni come preferibili ad altre), determinare che non contano (ad esempio perché anche se due possibili i sovraccarichi possono eseguire codice diverso, il programmatore ha indicato che dovrebbero comportarsi in modo identico in quei casi in cui potrebbero essere utilizzati) oppure segnalare quelli (e solo quelli) che non possono essere gestiti in uno dei due modi sopra.