Prima di tutto apprezzo il fatto che C# si stia avvicinando ai linguaggi funzionali prendendo in prestito cose interessanti.
Premetto però che non mi piace la parte di C# 3.0 "SQLizzata" (LINQ?) quindi mi astengo da qualsiasi giudizio in merito :-) Passiamo dunque alla feature succose che entreranno di prepotenza nel linguaggio (tanto per andare sempre di più verso Lisp che esiste da 50 anni...).
First class functions
Questo concetto esiste in quei linguaggi come Common Lisp, Python, Ruby, Haskell, Erlang (insomma tutti tranne quelli derivati dal C di cui sono a conoscenza). Essi supportano le funzioni come entità definibili a runtime, passabili come argomento e manipolabili come un qualsiasi tipo di dato. Un passo avanti dal concetto di funzione come semplice procedura con un valore di ritorno al concetto di funzione come dato. In C# tale meccanismo è simulabile (in parte) tramite i delegate, in C e C++ esistono i puntatori a funzione (delegate senza zucchero sintattico e funzionalità object oriented). C# 3.0 finalmente scavalcherà il confine permettendoci di creare le famigerate funzioni di ordine superiore che sono tanto care a chi abbia dimestichezza con i linguaggi funzionali ma anche con i linguaggi multi-paradigma.
Queste due funzionalità (funzioni first class e funzioni di ordine superiore) permettono di manipolare strutture dati in maniera molto più intuitiva e produttiva. Vantaggi pratici che mi vengono in mente sono l'implementazione del concetto di "currying", ossia la possibilità di creare una funzione che assegna al primo parametro di un'altra funzione un valore, oppure anche la composizione di funzioni. Quest'ultima in particolare viene in aiuto quando si devono richiamare funzioni con vari parametri (pensate ad un toolkit grafico) e il linguaggio non supporta funzioni con parametri di default.
Le opzioni, avendo funzioni come dati, sono infinite.
I delegate anonimi in C# 2.0 si avvicinano alla potenza delle funzioni first class ma hanno una sintassi ad oggetti, il che cozza tantissimo con lo scopo per cui esistono. Per questo e altri motivi C# 3.0 avrà le lambda (funzioni anonime) e un supporto alla programmazione funzionale nella libreria.
Hooray! :-)
Inferenza dei tipi
Personalmente non ho niente contro i linguaggi statici (anche se preferisco quelli a tipizzazione forte ma a runtime), però trovo inutile (e poco produttivo) il dover _esplicitare_ il tipo del dato in fase di dichiarazione. Se sto creando un intero, è ovvio che sia un intero. Se sto creando un'array di interi è ovvio che sia un'array di interi. Perchè non rendere il compilatore intelligente abbastanza per capire da sé qual è il tipo di dato della struttura o dell'oggetto primitivo che sto usando?
Ecco che il concetto di type inference si fa avanti. In breve: type inference significa che il sistema fa inferenza del tipo di dato dal contesto e dal valore che il nome (la variabile insomma) contiene. Questo permette di avere i vantaggi della tipizzazione statica senza le menate della dichiarazione esplicita.
C# 3.0 prende in prestito questo concetto (e quello discusso prima) da F# che è un derivato della famiglia ML (linguaggi funzionali impuri a tipizzazione forte e statica). Purtroppo in C# 3.0 la type inference è un pò castrata perché limitata alle lambda expression e alle variabili locali, ma è già qualcosa. La sintassi attualmente è questa:
var str = "hello";
var v = new Abc();
Io avrei tolto anche "var" ma va bene anche così :-)
Lazy evaluation
Il concetto di lazy evaluation è vecchio come il mondo. Haskell si basa fortemente su questo concetto, Oz la supporta dal giorno 1, Python ha creato un tipo di dato apposta (i generatori) per rendere la lazy evaluation un cittadino di prim'ordine. Lazy evaluation in soldoni significa ottimizzazione della risorsa memoria, significa anche computare un valore solo quando _realmente_ necessario e non sempre.
Questo significa, come ho detto, risparmio in termini di memoria e vantaggi in termini di velocità. Sempre prendendo a piene mani da Haskell (Microsoft Research usa Haskell moltissimo), C# 3.0 grazie alla lazy evaluation permetterà di creare strutture dati potenzialmente infinite il che si può tradurre in stream potenzialmente infiniti (vi si accende la lampadina se menziono Turing?). Senza lazy evaluation dovremmo avere memoria infinita, con invece, possiamo creare una struttura dati non finita anche sui nostri PC di casa.
Grazie alla lazy evaluation e alla funzioni first class la manipolazione di strutture dati sarà sicuramente più facile. Grazie a funzioni di ordine superiore come map() o filter() il codice sarà più semplice e descrittivo. Un pò di programmazione funzionale non fa di certo male :-)
Peccato che non ci siano le list comprehension in C# 3.0... ma non si può aver tutto dalla vita.
Tipi anonimi
C# 3.0 introduce anche il concetto di tipi anonimi che a mio avviso renderà il codice più "obfuscate" e non porta reali vantaggi data anche la loro strana sintassi e l'impiego specialmente per la parte che, come ho detto all'inizio, non tratto.
Per ora mi fermo qui, ci sarebbe da trattare il supporto alla meta-programmazione ma si merita un post a sé che magari un giorno mi verrà voglia di fare :-)