Manuel Paccagnella about blog search Subscribe to RSS Feed

Warning! This blog's new home now is here.

Imparare la programmazione funzionale

17 Nov 2014

(Un amico mi ha chiesto un consiglio su dove iniziare per imparare la programmazione funzionale, ri-pubblico qua la mia risposta leggermente adattata.)

FP in breve

Prima di tutto una breve parentesi riguardo la programmazione funzionale (FP) in generale. Non c'è una definizione universalmente accettata di FP, ma i tratti generali sono abbastanza comuni:

Queste caratteristiche hanno tutta una serie di grandi vantaggi in termini di (per esempio):

Il tutto ha una solida base teorica nel lambda calculus, un modello computazionale equivalente in termini di possibilità ma diverso da quello di Von Neumann.

Il modello di Von Neumann prevede una memoria condivisa e delle procedure che la alterano. Questo crea essenzialmente un accoppiamento temporale e spaziale tra diverse unità funzionali che, anche se gestito tramite oggetti, rimane una caratteristica intrinseca di questa architettura. Il che rende praticamente impossibile sfruttare facilmente il parallelismo offerto dalle odierne CPU multi-core.

In contrasto, il modello computazionale basato sul lambda calcolo si basa su trasformazioni di strutture dati immutabili da parte di funzioni pure. Il che come dicevo ha tutta una serie di vantaggi, non ultima la possibilità da parte del compilatore/interprete di sfruttare in molti casi automaticamente ed in modo trasparente il parallelismo.

Approccio didattico

Alcuni sostengono che il FP sia qualcosa di "alieno", "difficile", "impratico", "inutile". Cavolate! In realtà è piuttosto semplice ed estremamente utile e potente.

Il problema, piuttosto, è che semplicemente è qualcosa di un po' diverso da ciò che fin'ora è stato l'approccio mainstream. Ma anche il mainstream si sta rendendo conto che il FP è un requisito essenziale per poter lavorare in modo sano con concorrenza, parallelismo e sistemi distribuiti. Basti vedere la sempre maggiore popolarità di Clojure e Scala per esempio, ma soprattutto che anche Java si sta evolvendo in questa direzione. Già nella versione 8 sono state aggiunte le lambda expressions e gli stream. In ambito .NET poi, F# esiste già da tempo come cittadino di prima classe in Visual Studio. Senza contare Facebook che si sta orientando su soluzioni di stampo FP come Flux, basato su React.js e immutable-js.

L'ostacolo principale che ti troverai davanti all'inizio è che si tratta il tutto con una angolazione un pò diversa da quella a cui normalmente si è abituati proveniendo da un percorso "standard" di formazione. In realtà è semplice: c'è molta carne al fuoco certo, ma si costruisce tutto su solide e semplici basi. Perciò uno dei primi consigli che posso dare al riguardo è: sospendi il giudizio, e affronta l'argomento con mente aperta (con Shoshin, per evitare l'effetto Einstellung). Se ti applichi, ti posso assicurare che avrai una lunga serie di momenti "a-ha!!", che ti arricchiranno e miglioreranno professionalmente per il resto della tua vita (oltre a essere tremendamente eccitanti e soddisfacenti ;)

Ok, ma all'atto pratico da dove cominciare? Qualcuno direbbe: Scala! Ma essendo un misto-mare pieno di casi particolari e che tenta di "fondere" il paradigma OO con quello FP, rischia veramente di confonderti le idee. Oltre a non funzionare. Ha un type system più avanzato di quello di Java, ma la sua type inference è abbastanza limitata rispetto quella di Haskell per esempio. Ergo, secondo me più è diverso da ciò che già conosci, più facile è evitare che gli schemi di pensiero abituali ti rendano più difficili le cose.

Percorso

Haskell for all!

Per queste ragioni, tenderei a consigliarti di iniziare con Haskell. E' un linguaggio funzionale puro e staticamente tipato, che compila in codice nativo (quindi niente JVM nè .NET). Tieni conto che imparare questo stile migliorerà il tuo codice in qualsiasi linguaggio, anche se non utilizzerai Haskell o simili sul lavoro di tutti i giorni.

Il percorso che consiglio è quello delineato da Chris Allen. Per cominciare, ti consiglio caldamente il corso CIS 194 di Brent Yorgey dell'università della Pennsylvania. E' un corso molto completo e ben fatto. Puoi trovare qualche appunto (per ora sulle prime due settimane) sul blog del sottoscritto, ma a cui consiglio di dare uno sguardo solo dopo che hai affrontato il materiale di Brent Yorgey. Non è eccessivamente impegnativo, ma molto utile.

Altro consiglio: fai gli esercizi. Leggere e capire non significa assimilare, per imparare veramente occorre applicare le cose, solo allora ti rendi conto di ciò che sai e cosa no. L'unico apprendimento è quello attivo. Inoltre tieni presente che si parte dalle basi quindi non avere fretta di scrivere web application in quattro e quattr'otto. Tuttavia dalle basi si progredisce abbastanza velocemente, quindi persevera e vedrai ;)

Come ambienti di sviluppo io uso Emacs (vedi istruzioni di Chris Allen anche per questi aspetti), ma potresti anche usare FPComplete: un IDE web-based gratuito (nel cui sito tra l'altro ci sono molte risorse didattiche).

Padroneggiato un pò Haskell, le possibilità sono diverse:

Alternative track: Clojure

Anche Clojure è una buona scelta per imparare l'approccio FP. Ha bene o male tutti gli attributi necessari e fino a poco tempo fa era il mio linguaggio preferito. Di diverso rispetto ad Haskell:

Code is data, data is code.

Pur essendo un linguaggio marcatamente funzionale, un po' per scelta un po' per limitazioni della piattaforma sottostante, è da una parte più semplice di Haskell dall'altra ti assiste meno a tempo di compilazione tramite il type system. C'è core.typed certo, ma non è la stessa cosa. Questa differenza si nota molto a livello di impostazione e workflow: si usa molto la REPL e l'enfasi è sul modificare ed evoltere i sistemi manipolandoli direttamente a runtime (cfr. Smalltalk).

Di interesse la sua concezione del tempo, valori e identità (dello stato insomma) che facilita di molto la concorrenza. Da notare che la STM è presente anche in Haskell.

Clojure gira sulla JVM, ma anche su .NET e transpila su JS, interoperando con naturalezza con la piattaforma ospite.

Come risorse, se vuoi approfondirlo, ti consiglio:

Che ho esaminato meno da vicino, ma che ti segnalo comunque:

Dal punto di vista dello sviluppo, io uso Emacs ma ti segnalo anche:

Ci sarebbe molto altro da dire, ma per il momento basti questo. Ulteriori aree di indagine se sei interessato:

Altro?

Personalmente ti posso dire che parecchie delle cose imparate le sto applicando anche sul lavoro. In ambito Java per esempio sto usando molto TotallyLazy: sfortunatamente di documentazione c'è poco, ma ha una tonnellata di roba funzionale molto interessante. Comunque già solo col concetto di Callable e Sequence puoi fare molto e ti abilita un bel po' di idiomi funzionali (anche se non sempre convengono data la verbosità del linguaggio).

Interessante anche da esplorare lazyrecords (degli stessi autori), che fornisce un accesso ai dati funzionale a-la LINQ in ambito .NET.

Lato Javascript ci sono di interessanti da esplorare:

Ci sarebbe tantissimo altro da dire/esplorare/discutere, ma credo di aver già dato abbastanza materiale per ora.

blog comments powered by Disqus