Ciò che conta nei linguaggi di programmazione sono la semantica, non la sintassi. Tuttavia, la sintassi è un veicolo per la semantica. È facile dimostrare che due lingue possono avere una semantica incompatibile (ad esempio puntatori senza restrizione contro la sicurezza della memoria o differenze nei sistemi di tipi). Concentriamoci sulla sintassi e sulla semantica delle dichiarazioni delle variabili.
Quando dichiariamo una variabile in una lingua, questa variabile ha un tipo, un ambito e una durata.
La durata di una variabile determina per quanto tempo esiste il valore in quella variabile. Successivamente, quel valore viene liberato. In molte lingue, la durata è illimitata: un valore può essere utilizzato finché è accessibile, il garbage collector si occupa di liberare la memoria associata. Questo significa che non sappiamo staticamente quando un valore è liberato. Ma il C ++ garantisce la distruzione deterministica ed è un linguaggio frequente associare gli effetti collaterali alla distruzione. Questo non è possibile con la garbage collection. Questa linea ha un significato completamente diverso in C ++ e Java / C #:
Type variable = calculation();
Una sintassi universale richiederebbe una sintassi precisa del controllo della durata per poter esprimere una varietà di lingue.
Successivo: scoping. Scope determina dove è visibile un identificatore e si può accedere alla variabile. Esistono due tipi di scoping: lessicale / statico e dinamico. Con lo scope dinamico, una variabile è accessibile fino a un certo punto nel tempo ed è accessibile da qualsiasi codice che viene eseguito durante questo periodo. Esempi sono le variabili globali del pacchetto di Perl o le variabili "speciali" di Lisp. Più comune è lo scoping lessicale, in cui la variabile è visibile solo all'interno di una specifica regione del codice sorgente. Esistono tre modi in cui può iniziare l'ambito di una variabile:
- nell'istruzione in cui è dichiarata la variabile, che consente di utilizzare la variabile all'interno della sua definizione. Questo è importante se stiamo scrivendo un'espressione lambda ricorsiva.
- dopo l'istruzione in cui è dichiarata la variabile. Questo impedisce definizioni ricorsive.
- in una posizione diversa, ad es. l'inizio della funzione di chiusura o di un blocco che racchiude.
Questa affermazione ha un significato diverso in JavaScript (ambito di funzione) e C # (l'ambito inizia nell'istruzione):
var variable = calculation();
La sintassi universale dovrebbe fornire controlli di ambito precisi per una varietà di convenzioni per l'ambito.
Alcune lingue non fanno una differenza sintattica tra assegnazione e dichiarazione di variabili. Ciò è problematico quando una lingua presenta le chiusure, poiché questo ci impedisce di assegnare a variabili chiuse.
Finalmente, digitando. Molte lingue richiedono la digitazione statica esplicita, altre supportano un tipo di inferenza di tipo, altre non hanno tipi statici. Questa riga ha una semantica diversa in JavaScript e C #:
var variable = calculation();
In JavaScript, le variabili non hanno un tipo fisso, e possiamo liberamente assegnare un valore di un tipo diverso ad esso in un secondo momento. In C #, la parola chiave var
attiva l'inferenza di tipo e il tipo statico è determinato dal tipo di risultato del calcolo di assegnazione. A parte le differenze di scoping, l'equivalente C # sarebbe:
dynamic variable = calculation ();
E ci sono varie altre proprietà come la riassegnazione, le garanzie di sicurezza del thread o la coerenza dei valori che potrebbero essere riflesse in una dichiarazione di variabile. In nessun modo è possibile utilizzare una semplice istruzione come variable = value
di Python in una sintassi universale. Invece, potremmo avere a che fare con
let-in-function mutable thread-local dynamic* variable = value;
E a quel punto, la nostra sintassi universale è così ingombrante e fastidiosa che nessuno vorrebbe usarlo. La soluzione non può essere quella di escludere alcune combinazioni al fine di semplificare la sintassi, poiché alcune lingue hanno utilizzato questa combinazione per impostazione predefinita. Se la nostra sintassi non può esprimere la ricca varietà di semantica del linguaggio di programmazione, è difficilmente una sintassi universale.