Tag Archives: pattern matching

Programmazione funzionale in .Net 3.5: tutorial di base su F# (parte II)

Nota: per poter eseguire questo codice e’ necessario Visual Studio 2008 con installato il Microsoft F# Research Compiler (noi abbiamo usato la versione 1.9.1.3).

Prima di cominciare con il tutorial vero e proprio, e’ importante specificare perche’ questo linguaggio puo’ essere utile. Elenco i vantaggi principali senza entrare nel dettaglio:

questo paradigma e’ perfetto per il multithreading, che entro pochi anni diventera’ semplicemente irrinunciabile (quattro core? otto core? anche di piu’?)
F# e’ strettamente legato a C# e al mondo .Net in generale; si possono scrivere librerie in F# che poi possono essere lette e usate da C# nativamente, nonche’ viceversa
F# puo’ usare qualsiasi libreria .Net (XNA :) :) )
F# genera codice veloce
F# scrive codice logico/matematico semplicemente fantastico

In questo tutorial vedremo come si manipola la struttura dati che la fa da padrone nel mondo ricorsivo di F#: la lista!

Dichiariamo tre liste:

let l1 = [1;2;3;4] let l2 = 1::2::3::4::[] let l3 = l1@l2

l1 contiene i primi 4 interi, l2 anche ma e’ costruita effettuando una serie di operazioni di tipo “push” a partire dalla lista vuota []. Infine l3 e’ la concatenazione delle liste l1 e l2.

Come primo esempio di una funzione che manipola liste vediamo come sommare tutti gli elementi di una lista con una funzione ricorsiva:

let rec sum l = match l with [] -> 0 | x::xs -> x + (sum xs)

in cui vediamo come il pattern matching possa essere usato non solo per ispezionare il valore delle variabili, ma anche la struttura dei loro componenti (ad esempio qui distinguiamo tra la lista vuota [], la somma dei cui elementi e’ 0, e la lista con almeno un elemento x che va sommato alla somma del resto della lista).

Quindi vediamo in opera alcune cosiddette “funzioni di ordine superiore”, ossia funzioni che prendano in input anche altre funzioni per applicarle secondo pattern gia’ noti. Una delle piu’ semplici e’ la funzione di riduzione, ossia:

let rec reduce f l = match l with [] -> failwith “la lista non puo’ essere vuota” | [x] -> x | x::xs -> let acc = reduce f xs in f acc x

in cui la funzione f viene applicata alla riduzione della coda e all’elemento corrente. Se f fosse la funzione che ritorna il massimo tra due valori:

(fun a -> fun b -> if a > b then a else b)

allora reduce ritorna il massimo elemento della lista. Se invece come f usiamo la funzione somma:

(fun a -> fun b -> a + b)

allora reduce ritorna la somma di tutti gli elementi della lista. Esistono moltissimi altri patterns tipici di iterazione di liste e di collezioni, esattamente gli stessi che si trovano in LINQ (ed ecco perche’ abbiamo presentato LINQ come una estensione funzionale di C#, piuttosto che presentarlo come fanno molti come libreria per accesso ai databases).

Qui sotto il webcast tenuto da me (Giuseppe Maggiore) e da Giulia Costantini in cui produciamo questo codice (e molto altro) spiegando in dettaglio cosa significa e mostrando il risultato della sua esecuzione (download ad alta risoluzione qui):

[il webcast in streaming richiede silverlight e un attimo di pazienza per il caricamento; in compenso la visione puo' essere effettuata in full-screen a buona risoluzione!] Continue reading

Posted in Uncategorized | Tagged , , , | Leave a comment