Nel numero di febbraio 2011 della rivista ioProgrammo avevo pubblicato un articolo nel quale spiegavo come è possibile utilizzare una DLL, scritta e compilata in F#, all’interno di una soluzione Visual Basic. In quella occasione ho utilizzato una DLL open source (“Excel Financial functions for .NET”: http://bit.ly/hRBhCy), in alternativa all’utilizzo dei metodi disponibili nel namespace Microsoft.VisualBasic.Financial, per calcolare il tasso di interesse e l’importo totale da pagare per un prestito.
Purtroppo, l’attuale crisi economica ha reso quanto mai attuale l’idea di creare programmi di questo tipo, anche se ottenere un prestito è sempre più arduo.
Lasciamo comunque da parte questi pensieri tristi e dedichiamoci a qualcosa di più interessante e utile: magari potreste trovare il modo di “sbarcare il lunario” vendendo librerie di funzioni scritte in F#.
In questo articolo vedremo alcuni aspetti di F# in modo più approfondito, rispetto all’articolo che vi ho citato.
NOTA: potete scaricare i progetti presentati in questo articolo da questo indirizzo.
Un po’ di storia
La programmazione funzionale non è una novità di questi giorni: è un paradigma di programmazione che esiste almeno da 30 anni. Purtroppo non è stato adeguatamente supportato dai canali commerciali per vari motivi. Il mancato supporto deriva dalla convinzione che la programmazione funzionale sia adatta principalmente a problemi di carattere matematico, scientifico o finanziario. Questa concezione ha fatto sì che la programmazione funzionale fosse finora relegata ad àmbiti di tipo accademico, in laboratori di ricerca o in grandi istituti di statistica e di finanza (banche ecc.).
La situazione è cambiata da qualche anno, cioè da quando Microsoft ha deciso di investire sul linguaggio F# nei suoi laboratori di ricerca (Microsoft Research). Don Syme, l’inventore di F#, ha definito i costrutti del linguaggio partendo dalla sintassi dei precedenti linguaggi funzionali (OCaml, ML…) e aggiungendo le strutture che permettono di utilizzare istruzioni della programmazione imperativa e istruzioni della programmazione orientata agli oggetti, in perfetta integrazione con il .NET Framework.
Queste aggiunte hanno permesso a F# di uscire dai laboratori di ricerca per diventare un linguaggio multi-paradigma, utilizzabile anche in applicazioni commerciali.
Cosa fa F# che non fanno Visual Basic e C#?
F# non utilizza il non-valore Null e quindi il codice F# puro non può incorrere in eccezioni NullReferenceException.
In realtà è ancora possibile ottenere un NullReferenceException, ma solo in casi rari e particolari: utilizzando librerie VB/C#, tipi definiti in VB/C#, il valore null letterale e pochi altri casi.
Tuttavia il codice F# abbatte drasticamente i null utilizzati, rispetto ad analoghe applicazioni scritte in VB/C#, e di conseguenza la probabilità di ottenere un NullReferenceException è estremamente rara.
Un altro aspetto che rende F# uno dei linguaggi più robusti mai esistiti: è un linguaggio fortemente tipizzato ed è un linguaggio statico (non dinamico). Il compilatore, quindi, conosce in anticipo la maggior parte delle situazioni che possono portare a un’eccezione ed emette gli opportuni errori o avvertimenti.
L’ultimo aspetto su cui voglio soffermarmi è la straordinaria concisione di questo linguaggio, senza che però venga persa la chiarezza delle istruzioni e del flusso di esecuzione.
F# utilizza l’inferenza dei tipi per non dover dichiarare esplicitamente il tipo di dato di una “variabile” (o per meglio dire: di un “identificatore”, dato che le variabili utilizzate in F# sono immutabili, salvo che non venga indicato diversamente e in modo esplicito con la parola riservata mutable).
I blocchi di codice e i cicli non richiedono una apertura e una chiusura: è sufficiente aggiungere uno o più spazi di indentazione dove è opportuno. Niente parentesi graffe, niente punti e virgola, niente parole chiave di chiusura blocco (End …), niente di niente: solo ritorni a capo e spaziatura differente all’inizio di ogni riga di codice.
Tutto questo riduce enormemente il codice da scrivere, con la conseguenza di ridurne la complessità visiva, il tempo di digitazione e il tasso di errore (meno cose ci sono dentro, meno cose si rompono). Quello che aumenta è la semplicità, la produttività, la robustezza e la sicurezza.
F# linguaggio del futuro
Un’aspetto interessante di F# che sta diventando evidente è il fatto che questo linguaggio sia stato un precursore di alcune funzionalità che sono state poi implementate in Visual Basic e in C#.
LINQ, per esempio, nasce come un’estensione del .NET Framework con una natura prettamente funzionale.
In F# sono state sviluppate tecniche che sono state implementate successivamente anche in VB e in C#: per esempio la programmazione parallela, le funzioni asincrone, l’inferenza dei tipi.
Insomma, pare che il panorama della programmazione si stia gradualmente orientando verso il paradigma della programmazione funzionale, proprio per i vantaggi che questo può portare nella produttività e nella robustezza delle nostre applicazioni.
Conoscere F#, quindi, permette di precorrere i tempi ed essere sempre un passo avanti agli altri.
Cui prodest? A chi giova?
Dopo aver esposto “vita, morte e miracoli” di F#, sicuramente qualcuno si chiederà: “ma alla fine, dove posso utilizzare F#, per quali tipi di applicazioni?”.
Per quanto riguarda le piattaforme, F# è stato rilasciato anche con licenza open source e quindi può essere utilizzato in applicazioni Windows, ma anche in Linux (con Mono). Non disdegna il web, dato che può essere utilizzato in applicazioni ASP.NET e su applicazioni Windows Azure, né le applicazioni mobili, potendo essere utilizzato in applicazioni per Windows Phone.
Possiamo utilizzare all’interno di una finestra di Visual Studio (F# Interactive), direttamente da una “finestra DOS” (con gli eseguibili fsi e fsc), possiamo utilizzarlo come linguaggio di scripting, in applicazioni in puro F# o possiamo creare librerie F# da compilare in DLL e utilizzare in tutti gli altri ambiti (in applicazioni Visual Basic e C#, in ASP.NET, in Windows Azure, in Windows Phone ecc.). Insomma, la versatilità di questo linguaggio è enorme.
Ci sono alcuni ambiti in cui F# non è molto forte: se volete creare controlli visuali o interfacce utente, è meglio se vi orientate verso VB o C#. In ogni caso l’integrazione tra tutti i linguaggi .NET rende semplice creare applicazioni in linguaggio misto, dove F# fa la parte del leone nell’ottimizzare librerie di funzioni e VB/C# la fanno nella gestione di interfacce e controlli visuali.
La cassetta degli attrezzi
Purtroppo non è mai stata rilasciata una edizione Express di Visual F#, quindi dobbiamo scegliere tra una rosa di possibilità più limitata.
F# è naturalmente uno dei linguaggi che può essere installato durante l’installazione di Visual Studio 2012/2013 in versione completa (Professional o Ultimate).
Un’alternativa è quella di utilizzare un’IDE open source e gratuito come SharpDevelop: tra i modelli di progetti che possono essere creati ci sono anche le applicazioni Console in F#. Tuttavia, se proverete a creare un progetto di questo tipo otterrete un errore, perché dovete installare F#. Quest’ultimo potete trovarlo in licenza open source, quindi scaricarlo e installarlo, ma con un piccolo handicap: nel momento in cui sto scrivendo questo articolo la versione disponibile in open source è la 2.0, mentre con Visual Studio 2013 la versione disponibile è la 3.1 (in Visual Studio 2012 è presente la versione 3.0).
Ecco quindi una possibilità che possiamo sfruttare per poter lavorare in F# senza comprare Visual Studio:
1. installate “Visual Studio Express 2012 for Web” (http://bit.ly/1bgM3m7);
2. poi installate “F# Tools for Visual Studio Express 2012 for Web” (http://bit.ly/17Bf3Rx).
L’installazione di quest’ultimo software viene preceduta, in modo automatico e con un minimo intervento da parte dello sviluppatore, dall’installazione di “Microsoft Web Platform Installer”.
Microsoft Web Platform Installer è un software che ci permette di installare e aggiornare vari software e strumenti di sviluppo: per esempio fornisce i tool di supporto per Windows Azure, i tool di supporto per SQL Server (per esempio la Compact Edition), applicazioni CMS (come DotNetNuke, Orchard ecc.), blog, wiki e molto altro.
Dopo che avrete completato l’installazione di “F# Tools for Visual Studio Express 2012 for Web” potrete creare librerie F# e applicazioni web (ASP.NET e Windows Azure), sfruttando anche le grandi possibilità fornite dal linguaggio F#.
Bando alle ciance!
In questo articolo introduttivo su F# ho dovuto inquadrare un po’ qual è la sua storia, a cosa serve e come possiamo utilizzarlo. Dopo questa lunga trattazione su F#, sperando di non avervi annoiati, passo a qualche semplice esempio pratico.
In questo articolo affronteremo le seguenti tematiche, ciascuna con un suo esempio pratico:
-
F# Interactive in una finestra Prompt dei comandi;
-
F# Interactive in Visual Studio;
-
Applicazione interamente in F#;
-
Esecuzione di parti del programma;
-
Librerie in F#;
-
Windows Form con F#;
-
Applicazione VB/F# e C#/F# (con WPF);
-
Applicazione ASP.NET con F#
F# Interactive in una finestra Prompt dei comandi
Possiamo utilizzare F# in molti modi diversi. Uno di questi modi è quello di aprire una finestra del Prompt dei comandi (se avete Visual Studio potete aprire la versione specifica “per gli sviluppatori per Visual Studio 2012/2013”) e digitare fsi.
Una volta aperta la finestra del prompt dei comandi, possiamo digitare ed eseguire le istruzioni F# in modo interattivo (fsi = “FSharp Interactive”).
Per esempio possiamo scrivere l’istruzione
#help;;
per ottenere una breve guida su alcuni comandi che possono essere utilizzati, possiamo fare delle assegnazioni ed eseguire delle somme con la funzione let o “stampare” a video delle stringhe con le istruzioni printfn o printf.
L’istruzione printfn va a capo dopo aver visualizzato la stringa, mentre printf mantiene il cursore alla fine della stringa, così che un’eventuale altra stringa che viene stampata, viene posizionata concatenandola a quella precedente. Questo comportamento è perfettamente corrispondente all’utilizzo dei metodi Console.Write() e Console.WriteLine().
Nella Figura 1 potete vedere alcune istruzioni eseguite nella finestra del prompt dei comandi.
Noterete sicuramente che per eseguire le istruzioni è necessario aggiungere, alla fine della riga, un doppio carattere di punto e virgola (;;). Questo simbolo è necessario per far capire a FSharp che l’istruzione è terminata. Senza questo simbolo speciale possiamo continuare la scrittura dell’istruzione sulla riga successiva, almeno finché non abbiamo inserito il simbolo di fine istruzione. Notate però che l’utilizzo del simbolo “;;” di fine istruzione è necessario solamente nella modalità interattiva, mentre nei programmi compilati questa necessità non c’è, perché il compilatore è in grado di capire quando un’istruzione è terminata e quando inizia l’istruzione successiva. Come vi abbiamo già fatto notare, questa “intelligenza” del compilatore deriva dalla spaziatura delle istruzioni (indentazione) e dalla conoscenza di tutto il codice già inserito nel progetto.
L’istruzione let permette di assegnare un valore letterale o un risultato di una funzione o di un’espressione.
Notate anche che fsi definisce il tipo di dato restituito: in due casi abbiamo due int (Integer), mentre nell’ultimo caso abbiamo uno unit = (), perché la funzione printfn non restituisce alcun valore. Lo unit viene assegnato automaticamente a una variabile di nome it: questo è il nome predefinito che viene utilizzato quando non viene definita espressamente una variabile.
Degno di nota è anche il fatto che l’identificatore somma mantiene il valore assegnato nella prima istruzione, permettendo di utilizzarne il valore anche nella seconda istruzione. Questo significa che lo stato delle assegnazioni viene mantenuto durante tutta la sessione di F# Interactive, permettendo di scrivere ed eseguire un programma in modalità effettivamente interattiva.
Cosa succede se sbagliamo a digitare un’istruzione? Lo potete vedere nella Figura 2.
F# Interactive in Visual Studio
Una modalità di esecuzione di F# Interactive molto più comoda è quella che possiamo ottenere lavorando all’interno di Visual Studio.
Per lavorare con la finestra di F# Interactive non è necessario creare un progetto F# né altri tipi di progetto: è sufficiente selezionare la voce di menu Visualizza > Altre Finestre > F# Interactive, oppure basta premere molto più semplicemente la combinazione di tasti CTRL+ALT+F.
Come potete vedere nella Figura 3, possiamo eseguire le stesse istruzioni che abbiamo eseguito nel esempio precedente, esattamente con la stessa modalità (un’istruzione alla volta) e sostanzialmente con la stessa “esperienza utente”.
La finestra F# Interactive di Visual Studio e l’utilizzo di fsi.exe in Console sono indubbiamente utili per sperimentare singole istruzioni o semplici sequenze di istruzioni, specialmente quando avete appena iniziato a prendere confidenza con il linguaggio F#.
Ad un certo punto, però, sarà necessario andare un po’ oltre per poter sfruttare ulteriori vantaggi dall’ambiente di Visual Studio, come la possibilità di scrivere programmi più complessi e utilizzare le funzionalità di debug e di compilazione di programmi o di librerie di funzioni.
Il passo successivo, quindi, sarà costituito dalla creazione di programmi di tipo Applicazione F#.
Applicazione F#
Un’applicazione F# si crea semplicemente come tutti gli altri tipi di applicazione in Visual Studio: nel pannello sinistro della Start page selezionate Nuovo progetto oppure dal menu principiale selezionate File > Nuovo > Progetto. All’apparizione della finestra Nuovo progetto, selezionate il nodo Modelli > Visual F#, poi selezionate la voce Applicazione F# e compilate le informazioni nella parte inferiore della finestra: nome dell’applicazione, percorso, nome della soluzione, eventuale inclusione al controllo del codice sorgente (per esempio Team Foundation Server, Team Foundation Service sul web o anche all’analogo servizio CodePlex per progetti open source) e l’eventuale creazione di una sottodirectory per il progetto.
Nel file Program.fs troveremo il seguente codice di esempio:
#light
// Ulteriori informazioni su F# all'indirizzo http://fsharp.net
// Per ulteriori informazioni, vedere il progetto 'Esercitazione su F#'.
[<EntryPoint>]
let main argv =
printfn "%A" argv
0 // restituisci un intero come codice di uscita
Possiamo cancellare l’intero codice e scrivere quanto segue:
// esempio: mdgIntroFSharp01
open System
let mutable somma = 3 + 2
somma <- somma + 4
printfn("la somma di (3+2)+4 è uguale a 9")
let fine = Console.ReadLine()
Notate che abbiamo tolto la direttiva #light: lo possiamo fare perché l’impostazione di default è #light on. Tuttavia se volete maggiore chiarezza, potete lasciare tranquillamente tale direttiva nel codice (male non fa).
L’istruzione open System equivale all’istruzione import di Visual Basic: serve per utilizzare le classi e i metodi del relativo namespace senza dover necessariamente utilizzare utilizzare l’intera gerarchia di nomi: nel nostro esempio, cioè, possiamo utilizzare Console.ReadLine invece di System.Console.ReadLine.
La seconda istruzione (let mutable somma = 3 + 2) è simile all’esempio precedente, ma con l’aggiunta della parola riservata “mutable”. Questa parola permette di rendere l’identificatore somma una variabile modificabile. Per una questione intrinseca di F#, infatti, gli identificatori non sono variabili, nel senso che non permettono normalmente di modificare il loro contenuto, una volta che sono state definite e che gli è stato assegnato un valore. La mancanza della parola mutable nella seconda istruzione comporterebbe un errore nella terza istruzione, dato che il compilatore di F# segnalerebbe il duplicato della definizione dell’identificatore somma.
Nella terza istruzione, a questo punto non possiamo più utilizzare la funzione let, né possiamo utilizzare il simbolo di assegnazione (=). F# permette di assegnare a una variabile il valore di un’espressione, utilizzando un operatore di assegnazione inedito per gli sviluppatori Visual Basic e C#: il simbolo “freccia a sinistra” realizzato con due caratteri, cioè il simbolo “minore di” e il trattino (<-). Se ci ragioniamo un attimo, il significato è evidente: calcoliamo il valore dell’espressione “somma + 4” e lo assegniamo alla variabile posta alla sinistra dell’istruzione, cioè “somma”, utilizzando una freccia.
La quarta istruzione è identica a quella che abbiamo scritto nell’esempio F# Interactive.
Qui però troviamo una quinta istruzione che non avevamo utilizzato prima e che potrebbe risultare incomprensibile (let fine = Console.ReadLine()).
Il metodo Console.ReadLine() è utilizzato per evitare che la finestra della Console sparisca subito, dopo aver eseguito le istruzioni precedenti, rendendo difficile, se non impossibile, la lettura del contenuto della finestra. Con la quinta istruzione, quindi, il programma attende che l’utente prema il pulsante Invio prima di chiudere la finestra.
Questa è una tecnica che è utilizzata anche nei programmi Visual Basic e C#, quando sono progettati per essere eseguiti nella Console. La situazione, qui, è un po’ diversa perché il metodo ReadLine restituisce un valore che deve essere comunque assegnato a qualche variabile, anche se in questo caso non ci interessa leggere cosa ha inserito l’utente. Nelle applicazioni VB e C#, invece, possiamo invocare il metodo Console.ReadLine() senza assegnare il risultato a una variabile. Abbiamo quindi definito un identificatore “fine”, destinato a contenere la risposta dell’utente, sia essa una semplice pressione del tasto Invio oppure una stringa inserita prima della pressione di tale tasto.
Qui effettivamente l’assegnazione a un’identificatore non ha molto senso e rende l’istruzione un po’ strana. Possiamo quindi modificare l’istruzione per far sì che la risposta dell’utente venga ignorata, scrivendola in questo modo:
Console.ReadLine() |> ignore
In questo caso eseguiamo il metodo Console.ReadLine() ottenendo una risposta che viene “inviata”, con l’operatore di “pipe” (composto dalla barra verticale e da un simbolo “maggiore di”), verso la parola riservata ignore che indica che il valore restituito sarà ignorato.
Bisogna entrare nella mentalità di F# e dei linguaggi funzionali in generale: tutte le istruzioni devono essere delle funzioni che restituiscono un valore e tutti i valori restituiti devono essere in qualche modo utilizzati dal programma, oppure lo sviluppatore deve indicare espressamente al compilatore che un determinato valore non deve essere utilizzato, ovvero che deve essere ignorato.
Esecuzione di parti del programma
Un aspetto interessante dell’ambiente di sviluppo di Visual Studio è dato dalla possibilità di eseguire una unica istruzione oppure un blocco di istruzioni di un programma, senza dover necessariamente avviare l’esecuzione dell’intero programma.
È molto semplice: è sufficiente selezionare una o più istruzioni e premere la combinazione di tasti ALT+INVIO. Per esempio selezionate l’istruzione seguente:
let mutable somma = 3 + 2
somma <- somma + 4
e poi premete la combinazione di tasti che vi abbiamo indicato.
Vedrete che si aprirà automaticamente la finestra F# Interactive e sarà eseguito il blocco di istruzioni che avevate selezionato. Ecco il risultato per il nostro esempio:
val mutable somma : int = 9
val it : unit = ()
Questa modalità di esecuzione parziale è molto utile per testare piccole parti del programma, quando non vogliamo creare un progetto semplificato per fare degli esperimenti separati dallo sviluppo della nostra applicazione.
Libreria F#
Per sperimentare la creazione di una libreria F#, come primo esempio vediamo un’applicazione F# (soluzione mdgIntroFsharp02 e progetto con lo stesso nome) che utilizza un progetto di tipo Libreria F#. I passi da seguire sono i seguenti:
1. create una nuova soluzione con un progetto di tipo Applicazione F#, così come avevamo fatto nel primo esempio di applicazione di questo articolo;
2. cliccate con il tasto destro del mouse sul nome della soluzione (mdgIntroFsharp02) e selezionate la voce Aggiungi > Nuovo progetto;
3. nella scheda Visual F# selezionate il template Libreria F#, verificate che il percorso sia corretto (deve trovarsi preferibilmente nella sottocartella della soluzione, come il progetto principale) e indicate un nome di progetto (nel nostro caso abbiamo lasciato il nome predefinito Library1) e confermate premendo il tasto OK.
Vedrete che automaticamente verrà aggiunto il seguente codice:
type Class1() =
member this.X = "F#"
Il codice definisce un namespace di nome Library1, una classe di nome Class1 e una proprietà di nome X e contenente la stringa “F#”. Proviamo a modificare la libreria, sostituendo il codice con qualcosa di relativamente più utile:
// esempio: mdgIntroFsharp02
namespace Library1
type Stampa(x: string) =
static member testo(x) =
"Testo: " + x
Il codice è abbastanza banale: permette di restituire una stringa passata come parametro, concatenandola con il prefisso “Testo: ” (con uno spazio dopo i due punti, per una questione di esposizione visiva del testo). La sua banalità, però, ci permette di utilizzare questo semplice codice per vedere come può essere utilizzata la libreria in modo estremamente facile.
Alcune precisazioni: la prima riga contiene la dichiarazione del namespace Library1 a cui appartiene la libreria. Poi abbiamo dichiarato un tipo (cioè una classe) di nome Stampa. A seguire abbiamo dichiarato un metodo statico di nome testo che restituisce la stringa modificata.
Dopo aver scritto il codice, compilate il progetto Library1, cliccando con il tasto destro del mouse sul suo nome e selezionando Compila. Questo ci servirà per poter utilizzare la libreria compilata dal progetto principale.
Cliccate ora, sempre con il tasto destro del mouse, sul nodo Riferimenti del progetto mdgIntroFsharp02 e selezionate Aggiungi riferimento. Apparirà una finestra per la selezione dei riferimenti: cliccate sulla sezione Soluzione e selezionate la voce Library1, poi confermate premendo OK.
Aprite il file Program.fs del progetto mdgIntroFsharp02 e modificate il codice presente nell’editor con il seguente codice:
// esempio: mdgIntroFsharp02
open System
open Library1
let testo = Stampa.testo("Ciao mondo!")
printfn "%s" testo |> ignore
Console.ReadLine() |> ignore
()
Anche qui è bene specificare alcune cose, per comprendere bene il codice.
Le prime due istruzioni aprono o, per meglio dire, “includono” le librerie dei namespace System (del .NET Framework) e Library1 (cioè quella creata da noi).
L’istruzione let invoca il metodo Stampa.testo, passando come parametro una stringa da modificare.
La successiva istruzione stampa la stringa nella Console, segnalando che non ci interessa restituire un valore (vi ricordiamo che la “pipe” |> ignore è necessaria nella programmazione funzionale, quando non vogliamo utilizzare un valore di ritorno).
Poi abbiamo inserito un’istruzione in grado di leggere una stringa di input, con il solo scopo di “fermare” la chiusura della finestra della Console. Anche qui non ci interessa restituire un valore, né ci interessa cosa viene inserito dall’utente, bastando anche un semplice invio.
L’ultima riga può suscitare qualche curiosità: una coppia di parentesi tonde (). Questo è uno unit, cioè il valore/non-valore di cui abbiamo già parlato e che serve a indicare che il programma non restituisce valori significativi al chiamante o all’utente. Possiamo considerarlo un simbolo di chiusura del programma, anche se in alcuni casi potrebbe essere utile indicare un vero valore, per esempio un codice numerico per indicare una condizione di errore che si è verificata oppure un valore che rappresenta un risultato.
Dopo aver compilato l’intera soluzione, provate ad eseguire il programma: dovrebbe apparire ancora una volta la finestra del prompt dei comandi con il testo “Ciao mondo!”. La finestra resterà in attesa della vostra pressione di un tasto qualsiasi, dopodiché il programma terminerà chiudendo anche tale finestra.
Windows Form con F#
Un aspetto che emerge nella programmazione F#, all’interno dell’ambiente di sviluppo Visual Studio, è la scarsa, per non dire nulla, propensione di F# alla progettazione visuale.
Sebbene spesso si legga “Visual F#” nella documentazione disponibile, di “Visual” c’è ben poco, perché F# non è progettato per fornire supporto al trascinamento di elementi nell’interfaccia utente.
Questo non significa, però, che non si possa sviluppare un’applicazione F# in grado di visualizzare delle finestre con alcuni componenti visuali: semplicemente dobbiamo farlo da codice.
Nel prossimo esempio vedremo come si può creare un’applicazione Windows Form con F#, scrivendo del codice che, tutto sommato, non è molto complesso.
L’obiettivo che ci proponiamo di ottenere è quello di definire una finestra Windows Form, di posizionarvi un pulsante e di definire un evento Click, associato al pulsante stesso, per far apparire un messaggio.
// esempio: mdgIntroFsharp03
open System
open System.Drawing
open System.Windows.Forms
open System.Runtime.InteropServices // necessario per le API di Windows
// definizione delle API di Windows:
[<DllImport("kernel32.dll")>] extern System.IntPtr GetConsoleWindow()
[<DllImport("user32.dll")>] extern bool ShowWindow(System.IntPtr, int)
// riferimento all'handle della finestra “Prompt dei comandi”:
let h = GetConsoleWindow()
// la finestra “Prompt dei comandi” viene nascosta (0=hide):
ShowWindow(h, 0) |> ignore
// definizione della finestra Windows Form:
let form = new Form(Text="FsharpForm", Visible=true, Width=300, Height=300)
// definizione di un pulsante:
let btn1 = new Button()
btn1.Text <- "ClickME"
btn1.Location <- new Point(20, 20)
// aggiunta del pulsante all'insieme dei controlli del form:
form.Controls.Add(btn1)
// definizione del metodo da eseguire con l'evento Click del pulsante:
let btnClick _ =
MessageBox.Show("Click!") |> ignore
// aggiunta dell'evento Click:
let _ = btn1.Click.Add(btnClick)
// punto di ingresso dell'applicazione, con definizione del
// modello di threading COM come apartment a thread singolo:
[<STAThread>]
Application.Run(form)
Il codice è sufficientemente commentato, per cui non dovrebbero esserci problemi di comprensione sul suo funzionamento.
Vogliamo solamente attirare la vostra attenzione sulle istruzioni iniziali che servono a nascondere la finestra “Prompt dei comandi”. Infatti, se vogliamo utilizzare Windows Form come interfaccia utente, la vecchia “finestra DOS” è inutile e antiestetica, quindi vale la pena di aggiungere qualche istruzione per nasconderla.
Dopo aver avviato l’applicazione e cliccato sul pulsante, otterrete un risultato simile a quello che potete vedere nella Figura 5.
Applicazione VB/F# e C#/F#
Se non volete perdere tempo a definire l’interfaccia utente con F#, potete optare per la combinazione VB/F# oppure per quella C#/F#.
In questo caso, il progetto principale fornisce la struttura base dell’applicazione, sia dal punto di vista visuale, sia da quello del “comportamento” (eventi, interazione con l’utente ecc.), mentre tutta la logica e gli algoritmi più importanti vengono delegati a una libreria F#.
Questo fatto permette di utilizzare tecnologie visuali più recenti per la progettazione dell’interfaccia utente, come WPF o Silverlight.
Dato che in questo articolo abbiamo già visto come si scrive una libreria F#, in questo contesto non ci resta che definire l’interazione tra il codice VB e il codice F#.
Per prima cosa creiamo un progetto Visual Basic, utilizzando un template WPF, e lo chiamiamo mdgIntroFsharp04. Poi aggiungiamo un altro progetto, questa volta di tipo Libreria F#, denominato Library1.
Nella libreria F# inseriamo ancora una volta il codice seguente:
namespace Library1
type Stampa(x: string) =
static member testo(x) =
"Testo: " + x
Dopo aver compilato singolarmente il progetto della libreria F#, aggiungiamo il riferimento a Library1 nel progetto Visual Basic, così come abbiamo già visto negli esempi precedenti.
Quello che ci interessa di più, in questo momento, è la parte relativa al progetto Visual Basic.
Nella finestra del progetto principale aggiungiamo due caselle di testo e un pulsante.
La prima casella servirà per permettere all’utente di inserire una stringa di testo, mentre la seconda casella di testo mostrerà il risultato della funzione Stampa della libreria F#. Il pulsante, naturalmente, permetterà di chiamare la funzione e di mostrare il risultato.
Prima di tutto definiamo l’interfaccia utente con il seguente codice XAML:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="316" Width="525">
<Grid>
<TextBox x:Name="txtTestoInserito"
HorizontalAlignment="Left"
Height="56"
Margin="10,23,0,0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="497"
FontSize="36"/>
<TextBox x:Name="txtRisultato"
HorizontalAlignment="Left"
Height="54"
Margin="10,211,0,0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="497"
FontSize="36"/>
<Button
x:Name="btnCallStampa"
Content="Chiama funzione F#"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="361"
Margin="89,111,0,0"
Height="62"
FontSize="36"/>
</Grid>
</Window>
Il codice Visual Basic relativo al gestore dell’evento Click del pulsante è invece il seguente:
// esempio: mdgIntroFsharp04
Class MainWindow
Private Sub btnCallStampa_Click(
sender As Object, e As RoutedEventArgs) _
Handles btnCallStampa.Click
txtRisultato.Text =
Library1.Stampa.testo(txtTestoInserito.Text)
End Sub
End Class
Potete vedere l’applicazione funzionante nella Figura 6.
L’applicazione C# è sostanzialmente identica: cambia solamente il codice del gestore dell’evento Click che troviamo nel seguente frammento:
// esempio: mdgIntroFsharp05
using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace mdgIntroFsharp05
{
/// <summary>
/// Logica di interazione per MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnCallStampa_Click(
object sender, RoutedEventArgs e)
{
txtRisultato.Text =
Library1.Stampa.testo(txtTestoInserito.Text);
}
}
}
Applicazione ASP.NET/F#
Anche nell’ambito delle applicazioni web, l’interazione tra l’applicazione ASP.NET e la libreria F# non potrebbe essere più facile di così. Vediamo un breve esempio.
Prima di tutto creiamo un sito ASP.NET. Dopo aver selezionato la voce di menu File > Nuovo > Sito web, apparirà una finestra di selezione del tipo di applicazione (Figura 7).
Per semplificare, selezioniamo il template Sito web ASP.NET vuoto, scegliamo un percorso nel quale salvare i file dell’applicazione e confermiamo.
Una volta creata l’applicazione base, aggiungiamo un progetto di Libreria F#: su questo aspetto non ci soffermiamo oltre, perché la modalità di aggiunta della libreria, il codice contenuto nella libreria, la compilazione e l’aggiunta del riferimento nell’applicazione ASP.NET sono esattamente identici a quanto abbiamo già visto negli esempi precedenti.
Avendo scelto di creare un’applicazione ASP.NET vuota, tra i file del progetto non abbiamo nemmeno una pagina definita: aggiungiamo quindi una pagina di tipo WebForm (che nel nostro caso si chiama WebForm1.aspx) e modifichiamo il blocco <body> … </body> come segue:
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="txtTestoInserito" runat="server" Font-Size="24pt" Width="420
px"></asp:TextBox>
<br />
<br />
<asp:Button ID="btnCallStampa" runat="server" Font-Size="24pt" Text="Chiama funzione F#" Width="342px" />
<br />
<br />
<asp:TextBox ID="txtRisultato" runat="server" Font-Size="24pt" Width="420px"></asp:TextBox>
</div>
</form>
</body>
Come potete vedere, non abbiamo fatto altro che aggiungere due caselle di testo e un pulsante, esattamente come avevamo fatto negli esempi precedenti.
Ora dobbiamo solo modificare il codice che viene richiamato dalla pressione del pulsante: con un doppio click sul pulsante stesso, entriamo nell’editor del codice (Visual Basic o C#, a seconda del tipo di sito ASP.NET che avete scelto). Scriviamo quindi il seguente codice Visual Basic:
// esempio: mdgIntroFsharp06
txtRisultato.Text =
Library1.Stampa.testo(txtTestoInserito.Text)
oppure il seguente codice C#:
txtRisultato.Text =
Library1.Stampa.testo(txtTestoInserito.Text);
A questo punto potete compilare ed eseguire l’applicazione. Verrà avviato il web server incluso in Visual Studio e verrà aperto Internet Explorer per mostrare l’applicazione che abbiamo appena concluso. Se inserite un testo nella prima casella di testo e premete il pulsante, vedrete un risultato che ricalca quello che avete già visto nella Figura 6.
Alcune risorse per approfondire
In rete è possibile trovare parecchia documentazione su F#, anche se quasi esclusivamente in lingua inglese. In italiano, attualmente esiste quasi solo il blog dell’autore di questo articolo, reperibile all’indirizzo https://fsharpdazero.wordpress.com.
A seguire vi elenchiamo alcune risorse utili e interessanti che uno sviluppatore F# deve assolutamente conoscere.
MSDN Library
Si trova all’indirizzo http://bit.ly/15FalRk, ma è possibile scaricare tutta la documentazione anche in locale, utilizzando l’Help Viewer di Visual Studio 2012 (menu ? > Aggiungi e rimuovi contenuto della guida).
tryF#
All’indirizzo http://preview.tryfsharp.org/ è possibile trovare della documentazione e molti esempi pratici, ma il vantaggio principale è quello di poter eseguire il codice di esempio o il nostro codice F# direttamente online, senza utilizzare Visual Studio.
Visual F# Resources
All’indirizzo http://bit.ly/14llVa8 si trovano molte risorse per F#: riferimenti a documentazione, news, librerie, video, tutorial, esempi e così via.
Il blog di Don Syme
Nella vostra cassetta degli attrezzi non può mancare l’indirizzo al blog di Don Syme, cioè dello sviluppatore che ha creato Visual F#: http://blogs.msdn.com/b/dsyme/. Qui troverete articoli e annunci di novità che riguardano il linguaggio.
Rich Minerich’s Development Wonderland
Un altro blog che dovete assolutamente segnarvi è quello di Rich Minerich, sviluppatore F# e autore di vari libri su questo linguaggio: http://bit.ly/1akHpGO.
In questo blog trovate anche periodicamente un post con un immenso elenco di riferimenti a risorse su F#: news, articoli, librerie, video e molto altro.
Progetti su CodePlex
All’indirizzo http://bit.ly/150jzMo trovate un elenco di progetti open source (ben 69 progetti!) che potete scaricare, provare e utilizzare a vostro piacimento.
Channel 9
Per chi preferisce veder fare le cose in pratica e non ha particolare difficoltà a capire l’inglese parlato, non c’è niente di meglio che una serie di video. Li trovate su Channel 9 all’indirizzo http://bit.ly/18ubUVj.
FPish
Un altro riferimento importante è FPish, all’indirizzo http://cs.hubfs.net/. Si tratta di una community di sviluppatori F# e quindi vi potete trovare una grande varietà di contenuti, da vari blog a risposte su quesiti dei visitatori, fino a veri e propri corsi (questi però sono a pagamento).
Guida per la sopravvivenza
All’indirizzo http://bit.ly/15wxYMG potete trovare “The F# Survival Guide”, praticamente un libro-guida gratuito online. Dato il grande numero di esempi di codice è fortemente consigliato.
F# Snippet
Fortemente consigliato è anche il sito che si trova all’indirizzo http://fssnip.net/. A fronte di un’organizzazione del materiale forse un po’ caotica, potete trovare gli esempi per le varie categorie rappresentate da una “nuvola” di parole chiave presente all’inizio della pagina. Le parole chiave hanno una dimensione proporzionale al numero di esempi a cui si riferiscono.
La nuova versione 3.1 per Visual Studio 2013
Naturalmente un linguaggio del futuro deve continuamente aggiornarsi e aggiungere nuove caratteristiche. All’indirizzo http://bit.ly/14lnjcZ potete trovare l’annuncio delle novità della nuova versione 3.1 che sarà rilasciata contestualmente a Visual Studio 2013 (nel momento in cui scriviamo non è ancora stata resa pubblica la data di lancio).
Conclusioni
In questo articolo vi ho mostrato una panoramica su cosa è F#, su come è nato e su quale “filosofia” si basa, cioè la programmazione funzionale, unita alla programmazione imperativa e a quella orientata agli oggetti. Un linguaggio, quindi, multi-paradigma che ci consente una flessibilità mai vista prima, ma anche una robustezza senza precedenti.
Dopo aver esplorato alcuni aspetti che differenziano F# dagli altri linguaggi .NET (VB e C#) vi ho spiegato come installare F# anche sull’ambiente di sviluppo Visual Studio Express 2012 for Web. In seguito ho sperimentato l’esecuzione di istruzioni in F# Interactive e la costruzione di una libreria F#, utilizzata a sua volta da un programma F#, analizzandone anche le singole istruzioni.
Per motivi di spazio non ho potuto esplorare altre possibilità di F#: dall’utilizzo della libreria Library1 in VB e C# alla programmazione di interfacce Windows Forms con F#, dall’utilizzo di F# in siti ASP.NET e in applicazioni Windows Azure.