Namespace o Modulo?

Per chi proviene da C# o da VB, l’utilizzo dei namespace e dei moduli in F# può sembrare un po’ anomalo, ma si tratta semplicemente di abituarsi a una diversa convenzione.

Bisogna tenere presente un concetto fondamentale:

  • i namespace possono contenere solo dichiarazioni di tipi e NON possono contenere valori;
  • i moduli possono contenere dichiarazioni di tipi e ANCHE valori.

Ecco un breve esempio:

namespace X
type Tipo = { i : int; s : string }

namespace Esempio1

module Y =
type Tipo = { i : int; s : string }
let Tipo = (10,"prova")

Per prima cosa abbiamo creato il namespace X e, al suo interno, abbiamo definito un nuovo tipo di nome “Tipo” e formato da due identificatori: l’intero “i” e la stringa “s”.

Successivamente abbiamo definito il namespace “Esempio1” senza alcuna definizione al suo interno.

Infine abbiamo creato il modulo “Y”, definendo gli stessi tipi che avevamo definito nel namespace “X”, ma con in più anche l’assegnazione dei valori agli identificatori (ultima riga).

Notate che nel caso del modulo, abbiamo dovuto utilizzare l’operatore di assegnazione (=), posto subito dopo al nome del modulo.

Don Syme “ritwitta” l’indirizzo di questo blog!

Ieri ho pubblicato su Twitter l’indirizzo di questo blog italiano su F# e poco dopo ho ricevuto la notifica sul “ritwit” da parte di Don Syme (ved. il suo blog su MSDN http://blogs.msdn.com/b/dsyme/, ma anche il suo blog su FPish.NET http://fpish.net/blog/don.syme/).

Fsharp_RetwitDonSyme

Chi è Don Syme? La risposta la trovate al seguente indirizzo:
http://research.microsoft.com/en-us/people/dsyme/

Per vostra comodità trascrivo qui le sue stesse parole:

Don Syme

I am a Principal Researcher at Microsoft Research, Cambridge. I help Microsoft make better programming languages, and, through that, make people more productive and happier.

My main current responsibility is the design and implementation of F# (blog), though I’ve also worked on C# (being co-responsible for C# and .NET generics) and, indirectly, Visual Basic and other .NET languages.

As a researcher, my area is programming language design and implementation, with emphasis on making functional languages that are simpler to use, interoperate well with other languages and which incorporate aspects of object-oriented, asynchronous and parallel programming. I am interested in programming language perspectives on type inference, concurrency, reactivity, pattern matching and language-oriented programming. I also work extensively with teams in the Microsoft Developer Division on other programming-related technologies.

I am the primary author of Expert F#, published in 2007, and we are now working on a second edition of this book. In the past I have worked in formal specification, interactive proof, automated verification and proof description languages. I have a PhD from the University of Cambridge and am a member of the WG2.8 working group on functional programming.

Don’s Blog

F# Type Provider for MATLAB – Feedback requested, contributions welcome
Wed, 17 Jul 2013 21:59:08 GMT

F# Deep Dives – Chapter 4 – Financial Programming
Wed, 17 Jul 2013 21:27:00 GMT

F# Deep Dives – Early Access Program
Wed, 17 Jul 2013 21:18:00 GMT

F#/C# jobs in Machine Learning + Data Tools, Microsoft Research, Redmond
Thu, 11 Jul 2013 10:37:47 GMT

Tonight at F#unctional Londoners: More Machine Learning Hands-on with F#
Thu, 11 Jul 2013 10:31:16 GMT

Console application in F#: first time

Dopo circa un mese (troppo tempo!) sono riuscito a trovare il tempo necessario per scrivere l’articolo anticipato nel post precedente.
L’obbiettivo è semplice: creare un piccolo progetto console nel linguaggio F# e scoprire insieme le potenzialità che offre.

Aprendo Visual Studio 2013 ho creato un progetto “Console Application” nel linguaggio F# e subito ho notato due dettagli che meritano la nostra riflessione:

  • La versione del framework 4.5.1, ottenuta direttamente durante l’installazione di VS 2013, aggiunge diverse novità al linguaggio F# (rispetto a VB.NET e C#), tanto da meritarsi una nuova versione F# 3.1.
    Di conseguenza, se entriamo nelle proprietà del progetto, la schermata ci permette di scegliere quale runtime del linguaggio possiamo utilizzare per sviluppare la nostra applicazione.
  • Inoltre visual studio ci offre la possibilità di creare un tipo di progetto a se stante, denominato Tutorial, contenente un file ricco di esempi e di oggetti in codice F# utili per capire e soprattutto memorizzare la sintassi di questo linguaggio.

Tornando al nostro progetto, troveremo il “solito file program” che al suo interno racchiude l’entrypoint della nostra applicazione. Per chi non lo sapesse è il metodo eseguito per primo durante l’esecuzione del progetto e in F# la funzione di ingresso viene identificata con l’attributo [<EntryPoint>].
Nel nostro esempio faremo a meno di identificare l’entrypoint eseguendo il codice proceduralmente, in ordine di scrittura.

Esempio…

using System;
class Program
{
    static void Main(string[] args)
    {
         Console.WriteLine("Il risultato è: {0}",
CalcolaFattoriale(Convert.ToInt32(Console.ReadLine()))); Console.ReadLine(); } private static int CalcolaFattoriale(int _numero) { if (_numero > 0) return _numero * CalcolaFattoriale(_numero - 1); else return 1; } }

Come punto di partenza ho preso questo semplice codice C# che, sostanzialmente, dato un numero, ne calcola il fattoriale e restituisce il risultato. Naturalmente ci sono diversi modi per scrivere questa funzione e allo stesso modo la ricorsività del metodo di calcolo è utile esclusivamente a scopo dimostrativo. Inoltre, sempre per lo stesso motivo, ho cercato di tenere gli esempi più simili possibile, per evidenziare le vere differenze tra i due linguaggi.

Passiamo ora allo stesso codice scritto all’interno del nostro progetto F#

open System;

printf("Inserisci numero per calcolo fattoriale: ")

let _numero = Convert.ToInt32(Console.ReadLine())

let rec CalcoloFattoriale _numero =
    if _numero > 0 then _numero * CalcoloFattoriale (_numero-1) else 1

let res = CalcoloFattoriale _numero
printfn "Il risultato è: %A" res

let fine = Console.ReadLine()

Analizziamo ora, riga per riga questo codice.

  1. Nella prima semplicemente viene richiamato il namespace “System” come per il linguaggio C# o VB.NET rispettivamente attraverso “using” e “import”.
  2. Nella seconda inviamo alla console la stringa di testo, ma questa funzione è già stata introdotta nei primi post del blog da Mario de Ghetto.
  3. Nella terza eseguiamo un operazione di assegnazione di un valore. In verità però è molto interessante. Infatti possiamo notare quanto sia semplice far interagire oggetti di natura OOP del framework nei costrutti di F# di natura funzionale. Questo è possibile grazie alla interoperabilità intrinseca del Framework.
  4. Nella quarta riga invece avviene il cambiamento più radicale rispetto all’esempio C#. Con la parola chiave “rec”, preceduta da “let”, dichiariamo una funzione ricorsiva, ovvero in grado di richiamare se stessa. Questo permette di eseguire “calcoli ciclici” al proprio interno, restituendo ciò che ci interessa una volta soddisfatta la condizione.
    Da notare, come la possibilità di utilizzare funzioni ricorsive rende facile e veloce (in alcuni casi) la scrittura di codice rispetto che dichiarare una nuova funzione o utilizzare dei cicli for usati nella programmazione ad oggetti.
  5. Nelle ultime righe, viene chiamata la funziona ricorsiva, successivamente viene scritto il risultato nella console e infine con l’ultima si chiede alla console di aspettare l’input dell’utente prima di terminare l’esecuzione e chiudersi prematuramente.

Per concludere possiamo notare quanto sia immediato e di veloce scrittura utilizzare F# una volta afferrati i concetti base della programmazione funzionale.
Inoltre ho fatto un piccolo test, puramente indicativo, utilizzando la classe Stopwatch del namespace System.Diagnostic sulla funzione ricorsiva di F# e sulla chiamata ricorsiva di C# e, come mi aspettavo, è risultata molto più performante quella funzionale.
In questo esempio è comunque poco indicativo, infatti utilizzando dei cicli while o for nel codice C# si otterrebbero dei risultati migliori.

Nel prossimo post vorrei approfondire meglio con qualche esempio più complesso quando è effettivamente utile integrare nelle nostre applicazioni codice funzionale o meno. Vedere quando esso porti un netto miglioramento nelle prestazioni o nell’immediatezza e facilità di scrittura delle nostre applicazioni.

Un saluto, a presto
Michael

if … then … elif … else

Uno dei costrutti più facili da capire in F# è il costrutto if … then, anche perché è estremamente simile all’istruzione If … Then di Visual Basic.

La forma più semplice è quella che potete vedere in questo frammento di codice:

System.Console.Write("Inserisci la tua età: ")
let eta = System.Console.ReadLine()
let numero = int eta
if numero < 18 then
   System.Console.WriteLine("Sei minorenne!")
else
   System.Console.WriteLine("Sei maggiorenne")

System.Console.ReadLine() |> ignore

    Il funzionamento è il seguente:

  1. nella prima riga viene mostrata una stringa che rappresenta il “prompt”, cioè la richiesta all’utente;

  2. nella seconda riga leggiamo una stringa di input dall’utente e la associamo all’identificatore “eta”;

  3. nella terza riga effettuiamo una conversione della stringa in intero (int) e associamo il risultato all’identificatore numero;

  4. nella quarta riga inizia il costrutto “if … then” con il test sul numero inserito. Il test verifica se l’età è inferiore a 18. Notare che il test fornisce un risultato che è un booleano (vero o falso);

  5. la quinta riga viene eseguita se l’età è inferiore a 18 e quindi visualizza la stringa “Sei minorenne!”;

  6. nella sesta riga troviamo la parola “else” che indica un ramo alternativo del costrutto “if … then” che viene percorso se il test è falso;

  7. nella settima riga viene visualizzata la stringa “Sei maggiorenne”;

  8. infine, nell’ultima riga, attendiamo la pressione di un tasto per chiudere la finestra della Console (altrimenti non vedremmo il risultato del programma). Notare l’operatore di “pipe” |> che invia il risultato della funzione a “ignore”, per ignorarlo ed evitare segnalazioni di errore da parte del compilatore.

    1. Una possibile variante del costrutto “if … then” prevede l’aggiunta di ulteriori “rami” di scelta, con la parola “elif” (che in Visual Basic si leggerebbe Else If).

      System.Console.Write("Inserisci la tua età: ")
      let eta = System.Console.ReadLine()
      let numero = int eta
      if numero < 18 then
         System.Console.WriteLine("Sei minorenne!")
      elif numero > 64 then
         System.Console.WriteLine("Sei anziano")
      else
         System.Console.WriteLine("Sei maggiorenne")
      
      System.Console.ReadLine() |> ignore

      Come potete vedere abbiamo aggiunto il ramo “elif” che verifica se l’età è superiore a 64 e, in tal caso, visualizza la stringa “Sei anziano” (il termine “anziano” viene comunemente utilizzato per definire le persone da 65 anni in su, mentre “grande anziano” è la persona con un’età uguale o superiore a 75 anni).

      Esploriamo anche la possibilità di aggiungere un numero indefinito di “elif”:

      System.Console.Write("Inserisci la tua età: ")
      let eta = System.Console.ReadLine()
      let numero = int eta
      if numero < 18 then
         System.Console.WriteLine("Sei minorenne!")
      elif numero > 74 then
         System.Console.WriteLine("Sei un 'grande anziano'")
      elif numero > 64 then
         System.Console.WriteLine("Sei anziano")
      else
         System.Console.WriteLine("Sei maggiorenne")
      
      System.Console.ReadLine() |> ignore

      Una cosa che si può fare in F#, diversamente da Visual Basic e da C#, è utilizzare il costrutto “if … then” come funzione, all’interno di un’istruzione di assegnazione. Ecco un esempio:

      System.Console.Write("Inserisci la tua età: ")
      let eta = System.Console.ReadLine()
      let numero = int eta
      let risposta = 
          if numero < 18 then
             "Sei minorenne!"
          elif numero > 74 then
             "Sei un 'grande anziano'"
          elif numero > 64 then
             "Sei anziano"
          else
             "Sei maggiorenne"
      System.Console.WriteLine(risposta)
      System.Console.ReadLine() |> ignore

      Come potete vedere, nella quarta riga abbiamo definito l’identificatore “risposta” e gli abbiamo assegnato il risultato del costrutto “if … then”. Inoltre, nei vari rami di questo costrutto abbiamo inserito solamente la stringa da restituire e che sarà il valore che verrà assegnato all’identificatore “risposta”. Subito dopo abbiamo inserito un’istruzione per scrivere il risultato nella Console.

      Articolo di presentazione di Michael Ciceri

      Con questo articolo dò il benvenuto a Michael Ciceri che ha aderito al mio progetto di studio e di divulgazione del linguaggio F#. Lascio subito a lui la parola!

      Salve a tutti,

      Prima di iniziare a discutere con voi delle mie prime impressioni su questo fantastico linguaggio, F#, vorrei ringraziare Mario de Ghetto per avermi dato la possibilità di pubblicare questo post nel suo blog.

      Mi presento. Mi chiamo Michael Ciceri. Per chi non mi conoscesse sono un appassionato di tutto ciò che riguarda l’informatica, in particolare del “.Net World” e di conseguenza di tutte le sue implicazioni, e
      svolgo l’attività di analista programmatore come consulente.

      Finalmente, dopo molte peripezie, ho trovato il tempo di intraprendere la conoscenza di questo linguaggio funzionale che fin dai suoi esordi mi ha sempre suscitato enorme interesse, per una serie di motivi e caratteristiche fulcro di questo mio primo post.

      Pensare di avere la possibilità di coniugare programmazione ad oggetti e programmazione funzionale è stato il primo vero interesse che mi ha motivato a provare questo linguaggio. Come accade per C# e VB.Net è possibile utilizzare F# e integrarlo perfettamente nelle nostre applicazioni e viceversa, in vero stile .Net, ovvero senza sforzi.

      Questo porta direttamente al secondo punto a suo favore: la programmazione funzionale offre caratteristiche diverse che permettono di estendere e migliorare le nostre applicazioni utilizzando però una architettura o semplicemente un metodo diverso per costruire il nostro “core”.
      In parole povere, ci sono funzioni o porzioni della struttura dell’applicazione che, scritte in F# e quindi pensate in ambito funzionale, hanno molto più senso.

      Questo mi porta a vedere F# come un’estensione del mondo .Net ad oggetti, migliorandone appunto il suo utilizzo. Infatti negli ultimi anni ci siamo già abituati ad utilizzare concetti funzionali. Basta pensare a LINQ e alle Lambda expression. Tuttavia, ciò non toglie il fatto che come ogni altro linguaggio o tipo di programmazione, sia possibile programmare interamente in F# in molti, se non tutti gli ambiti con i pro e contro del caso.

      Dopo queste macro riflessioni, che pur essendo interessanti rimangono comunque teoriche, è fondamentale provare ad utilizzare F#.
      Mario de Ghetto con i suoi post sta già facendo un gran bel lavoro certosino, completo e semplice.
      Nel prossimo topic cercherò di puntare, con qualche esempio, a concetti un po’ diversi con un approccio differente. Partiremo con la creazione di un progetto console in F# e vedremo insieme come sviluppare una semplice funzione con lo scopo preciso di scoprire le caratteristiche del linguaggio stesso.

      Un saluto, Michael

      Visual Studio 2015

      20 luglio 2015: ancora una volta Microsoft arriva all’appuntamento puntuale, con l’atteso rilascio di Visual Studio 2015 per gli abbonati MSDN e, in versione di prova, per chi non è abbonato (https://www.visualstudio.com/downloads).

      image

      Nella pagina di download potete trovare anche la versione Visual Studio Community, una particolare versione che include tutti i template delle varie versioni di Visual Studio Express, in modo che possiate avere tutto in un unico prodotto, come nel caso di Visual Studio “full”. Ovviamente questa è una versione che ha alcune limitazioni, in particolare non può essere utilizzata in organizzazioni che non abbiano una piccola dimensione. Nelle organizzazioni medio-grandi è opportuno utilizzare Visual Studio “full”, soprattutto se lavorate in team di sviluppo abbastanza strutturati e “corposi”.

      Ecco un po’ di documentazione, per capire quali sono le novità…

      Annuncio ufficiale nel blog di Somasegar

      http://blogs.msdn.com/b/somasegar/archive/2015/07/20/visual-studio-2015-and-net-4-6-available-for-download.aspx

      Channel 9 – Visual Studio 2015 Final Release Event

      https://channel9.msdn.com/Events/Visual-Studio/Visual-Studio-2015-Final-Release-Event

      Channel 9 – oltre 60 video on-demand sulle caratteristiche

      http://blogs.msdn.com/b/somasegar/archive/2015/07/20/visual-studio-2015-and-net-4-6-available-for-download.aspx

      image

      ATTENZIONE: dato che il 29 luglio 2015 è la data prevista per l’aggiornamento automatico di Windows 7 e di Windows 8.x alla versione Windows 10 e dato che Visual Studio necessità di Windows 10 per installare i tool di sviluppo aggiornati per le Universal Apps per Windows 10, è opportuno che l’installazione di Visual Studio 2015 avvenga dopo l’aggiornamento di Windows, altrimenti qualcosa non funzionerà. Vi consiglio quindi di effettuare l’installazione in una virtual machine “usa e getta”, se proprio non riuscite a trattenervi…  🙂

      Le costanti Infinity e -Infinity

      Trattando con espressioni matematiche può capitare di incorrere nella divisione di un numero per zero. Normalmente una divisione per zero incorre in un’eccezione DivideByZeroException, come si può vedere nella figura seguente:

      image

      Notate però che l’operazione di divisione è eseguita tra due valori interi.

      Se invece degli interi utilizziamo valori reali (cioè numeri a virgola mobile o floating-point), il risultato sarà il seguente:

      image

      Come potete vedere, le due operazioni danno un risultato completamente differente: +Infinito e –Infinito.

      +Infinito e –Infinito (o +Infinity e –Infinity nella versione inglese) sono due costanti a virgola mobile utilizzate da F#.

      Unità di misura

      Una delle caratteristiche di F# di cui non troviamo corrispondenza in Visual Basic e in C# è quella delle “units-of-measure”, cioè delle unità di misura.

      Nei calcoli scientifici è molto importante utilizzare le corrette unità di misura: per esempio, per una distanza si utilizzano i metri <m>, per una unità di tempo si potrebbero utilizzare i secondi <sec>, per una velocità i metri al secondo <m/sec>, mentre per un’accelerazione si utilizzano i metri al secondo al quadrato <m/sec^2>.

      Un altro aspetto importante delle unità di misura è la possibilità di effettuare delle conversioni da un’unità di misura ad un’altra (per esempio da gradi Centigradi a gradi Fahrenheit) oppure da un’unità di misura a unità di misura più piccole o più grandi (da chilogrammi a grammi oppure a tonnellate).

      Una unità di misura di dichiara come segue:

         1: [<Measure>] type m
         2: [<Measure>] type sec
         3: [<Measure>] type kg

      poi si utilizza come segue:

         1: let distance = 1.0<m>    
         2: let time = 2.0<sec>    
         3: let speed = 2.0<m/sec>    
         4: let acceleration = 2.0<m/sec^2>    
         5: let force = 5.0<kg m/sec^2>   

      Come potete vedere, abbiamo dichiarato le unità di misura m (metri), sec (secondi) e kg (chilogrammi) e poi abbiamo dichiarato degli identificatori come la distanza (espressa in metri), un tempo (espresso in secondi), una velocità (espressa in metri al secondo), un’accelerazione (espressa in metri al secondo quadrato) e una forza (chilogrammi per metro al secondo quadrato).

      Naturalmente è possibile definire anche delle unità di misura derivate, come nel seguente esempio:

         1: [<Measure>] type N = m/sec^2
         2: let force1 = 5.0<kg m/sec^2>    
         3: let force2 = 5.0<N>

      Il vantaggio di dichiarare una unità di misura è il fatto che il compilatore è in grado di verificare tutte le espressioni utilizzate e segnalare quelle che sono incongruenti. In sostanza non è possibile “sommare mele e pere”, perché sono due entità diverse. Si possono sommare metri a metri, chilogrammi a chilogrammi, non è possibile invece sommare metri a chilogrammi perché è un calcolo che non ha alcun senso.

      Alcuni articoli utili su questo argomento sono i seguenti (in lingua inglese):

      http://msdn.microsoft.com/it-it/library/dd233243.aspx
      http://fsharpforfunandprofit.com/posts/units-of-measure/
      http://davefancher.com/2012/11/18/f-more-on-units-of-measure/
      http://trelford.com/blog/post/Runtime-Units-of-Measure-for-F.aspx

      I cicli For

      In questo post voglio mostrarvi come si usa un ciclo for, costrutto importantissimo che è probabilmente presente in tutte le applicazioni.

      Partiamo da un frammento di codice come questo:

         1: #light
         2: let results = [ for i in 0 .. 100 -> (i, i*i) ] 
         3: printfn "results = %A" results 

      Notate, nella prima riga, la direttiva #light che abbiamo già incontrato in un post precedente. Questa è una semplificazione per i programmatori “non-OCaml” che si avvicinano al linguaggio F# e può anche essere omessa, perché è predefinita.
      Il frammento di codice sembra banale, ma non lo è. Come potete vedere dalla figura seguente, restituisce un risultato che corrisponde a una lista.

      image

      Una lista è un costrutto primitivo utilizzato di frequente nei linguaggi funzionali e molto simile a una matrice. Tuttavia, una lista non consente un accesso basato sulla posizione, come la tradizionale sintassi a[i] di C#. Le liste sono utilizzate in molte occasioni nella programmazione funzionale e possono essere considerate l’equivalente in F# di List<T> del .NET Framework, anche se con alcune funzionalità migliorate.

      Una lista è sempre di tipo particolare e, in questo caso, l’identificatore results rappresenta un elenco di tuple, specificamente il tipo di tupla identificato in F# come tipo (int * int).

      Questa idea di una lista di tuple è familiare se considerata come l’equivalente di una coppia di colonne restituite da un’istruzione SELECT in SQL. Pertanto, nell’esempio viene creata essenzialmente una lista di coppie di numeri interi composto da 100 elementi.

      Comunemente, nei linguaggi funzionali, le definizioni delle funzioni vengono utilizzate ovunque sia possibile utilizzare il codice stesso. Pertanto, se si desidera estendere l’esempio precedente, potete scrivere quanto riportato di seguito:

         1: let compute2 x = (x, x*x)
         2: let compute3 x = (x, x*x, x*x*x)
         3: let results2 = [ for i in 0 .. 100 -> compute2 i ]
         4: let results3 = [ for i in 0 .. 100 -> compute3 i ] 

      Ecco quindi le due liste risultanti dall’esecuzione del frammento di codice riportato qui sopra:

      image

      Questa idea di eseguire un ciclo in una lista (o una matrice o qualche altro costrutto iterabile) è un’attività talmente comune nei linguaggi funzionali che è stata generalizzata come chiamata di metodo di base: List.iter. Questa funzione prevede semplicemente una chiamata a una funzione in ciascun elemento della lista.

      Funzionalità molto utili sono inoltre fornite da altre funzioni di libreria simili. Ad esempio, List.map accetta una funzione come argomento e applica la funzione a ciascun elemento della lista, restituendo una nuova lista nel processo.

      Utilizzare F# su LINUX, MAC, Android, iPhone ecc. ecc.

      Oltre che su Windows, F# può essere utilizzato su Linux, a patto di aver installato Mono. Inoltre può essere utilizzato anche su altre piattaforme come MAC, Android, iPhone, FreeBSD ecc. ecc… Il problema è: “come si fa?”.

      Alla pagina http://fsharp.org/use/linux/ trovate la guida per installare Mono e F# su Linux, mentre nelle altre pagine (i cui link sono elencati nella colonna di sinistra, nella stessa pagina, nella sezione “Getting F#”) trovate i riferimenti per le altre piattaforme.

      image

      F# in pillole: Unit Type ovvero ()

      Nella programmazione funzionale deve essere sempre restituito un valore. Tuttavia ci sono alcuni casi in cui il valore non c’è, per esempio quando utilizziamo la funzione printf. In questi casi, in fase di compilazione riceviamo un warning, cioè un avvertimento di possibile errore.

      Per risolvere in modo pulito queste situazioni, possiamo utilizzare il tipo unit che è rappresentato da una coppia di parentesi tonde, cioè (). La restituzione di uno unit equivale più o meno al void di altri linguaggi.

      In F# non c’è il concetto di Null, non esiste un valore o meglio un “non-valore” nullo, mentre esiste il tipo unit che fornisce un unico valore: ().

      Un codice di esempio che rappresenta quanto detto è questo:

      // con questo codice si ottiene un warning in compilazione:
      let function1 x y = x + y
      function1 10 20 
      
      // questo è invece valido e restituisce uno unit = ()
      let result = function1 10 20
      function1 10 20 |> ignore

      L’operatore |> indica un “pipe”, ovvero un redirezionamento del risultato verso un’altra funzione o verso un’output. In questo caso si ottiene uno unit.

      Anche se F# permette l’utilizzo di funzioni/istruzioni non prettamente funzionali, è opportuno utilizzare il paradigma funzionale in tutti i casi in cui è possibile, per poter ottenere un codice il più possibile sicuro e “pulito”.

      “Eager evaluation” (detta anche “greedy evaluation”) e l’opposto “Lazy evaluation”

      F# include un componente di programmazione funzionale che supporta la cosiddetta “Eager evaluation”, detta anche “Greedy evaluation”. Per la programmazione funzionale, questo componente fornisce vari costrutti e un insieme di tipi immutabili: tuple, record, unioni discriminate e liste.

      Il termine “Eager” significa sostanzialmente “impaziente, avido” ed è all’opposto di “Lazy”, ovvero “pigro”.

      Nella eager evaluation, un’espressione è valutata non appena viene assegnata a una variabile (che nel caso di F# è opportuno chiamare “identificatore”), mentre nella lazy evaluation l’espressione è valutata solo nel momento in cui è richiesto il risultato.

      Vediamo ora i tipi immutabili di cui ho fatto cenno all’inizio di questo post.

      n-tuple

      Una n-tupla rappresenta una collezione di “n” valori, dove “n” è maggiore o uguale a zero.

      Il tipo  unit  corrisponde alla 0-tupla e ha un solo valore:  (), che indica “nessuna informazione” (sostanzialmente l’insieme vuoto).

      Il tipo unit è utilizzato per implementare funzioni che non hanno necessità di input e/o non restituiscono valori.

      Una 3-tupla potrebbe essere rappresentata da  (A, B, C), dove A, B e C sono valori di possibili differenti tipi.

      Una tupla può essere utilizzata solo per memorizzare valori quando il numero di valori stessi è conosciuto al momento della definizione (a design-time) e rimane costante durante l’esecuzione.

      record

      Un record è una specializzazione delle tuple dove gli elementi dei dati sono denominati, come in { Name: string; Age: int}.

      I record possono essere creati con la forma  { Name = “AB”; Age = 42 }.

      La parola riservata with è utilizzata per creare una copia di un record, per esempio { r with Name = “CD” }, che crea un nuovo record copiando r e cambiando il valore del campo Name (assumendo che il record creato nell’ultimo esempio sia denominato r).

      liste

      Il tipo list è una normale linked list rappresentata in due varianti:

      • una notazione head::tail (:: è l’operatore cosiddetto “cons”, per dividere due parti di una lista)

      • una notazione abbreviata come [item1; item2; item3].

      Una lista vuota è scritta con la notazione [].

      unioni discriminate

      E’ un altro tipo di dati algebrico che può essere definito per mantenere un valore di un tipo previsto tra quelli predefiniti. Per esempio:

      type A = 
         | valX of string
         | valY of int

      let

      Per dichiarare un identificatore (non chiamateli variabili, per favore!), si utilizza la parola riservata let.

      Ma questa è un’altra storia…

      (F#) Project Euler .net – Problema n. 1

      Molto spesso, per imparare un nuovo linguaggio di programmazione, si esaminano alcuni problemi matematici. Questo avviene per due motivi: il primo è motivo deriva dal fatto che molti piccoli problemi matematici sono molto semplici e quindi non aggiungono livelli di complessità all’attuale nostro problema di imparare un particolare linguaggio di programmazione. Il secondo motivo è dato dal fatto che questo approccio consente di imparare in modo più efficace i costrutti di base della programmazione nel linguaggio scelto: cicli, istruzioni condizionali, assegnazione di valori, visualizzazione del risultato e così via.

      Un sito interessante che raccoglie molti di questi problemi matematici, in ordine di difficoltà crescente, è “Project Euler .net” (http://projecteuler.net). Potete registrarvi al sito per provare a dare le vostre soluzioni. Quando fornirete una soluzione corretta, vedrete nel vostro “pannello” dei problemi le soluzioni trovate e potrete anche visualizzare un file PDF contenente una spiegazione dettagliata della soluzione proposta.

      Utilizzerò pertanto qualcuno di questi problemi per costruire il nostro “vocabolario” delle istruzioni di F#. Il fatto che il sito abbia il suffisso “.net” è solamente un caso: non ha alcuna attinenza con il Framework .NET  clip_image001

      Il primo problema consiste nell’esaminare e sommare tra loro tutti i multipli di 3 e di 5 in un intervallo di numeri naturali che va da 1 a “x”. Per esempio, tra 1 e 9, la somma dei multipli di 3 e 5 è pari a 23 (= 3+5+6+9).

      Trovare la somma di tutti i numeri multipli di 3 e di 5, tra 1 e 999.

      Possiamo risolvere questo problema in almeno due modi (ma probabilmente anche in molti altri). In entrambi i casi otteniamo il numero 233168.

      La prima soluzione è la seguente:

      #light
      let rec sum_mul xs =
         match xs with
            | [] -> 0
            | y::ys when y % 3 = 0 || y % 5 = 0 -> y + sum_mul ys
            | y::ys -> sum_mul ys
      let sum = sum_mul [1 .. 999]
      printfn "%d" sum

      Esaminiamo come funziona questa prima soluzione.

      La direttiva #light permette di scrivere il codice in modo più semplice, senza le parole chiave begin … end e senza altri caratteri che indicano il termine delle righe di istruzione (come il “;” di C#, per esempio). I cicli o i blocchi di codice sono definiti dall’indentazione del codice (cioè dai rientri), mentre il termine delle istruzioni è semplicemente riconosciuto dalla presenza di spazi e di ritorni a capo.

      Nella seconda riga abbiamo inserito una funzione ricorsiva, denominata sum_mul, che accetta il parametro xs.

      Nelle righe dalla 3^ alla 6^ c’è un esempio di pattern matching: un metodo elegante per gestire varie alternative (come uno switch o un select case). Il programma confronta xs con alcuni pattern, ciascuno scritto in una riga separata e preceduti dal simbolo “|” (pipe). Nel primo caso il confronto ha successo quando xs è una lista vuota e in tal caso sum_mul restituisce 0 (zero).

      Negli altri casi, xs corrisponde a una lista, in cui il primo elemento (la testa della lista) viene chiamato y e il resto della lista (la coda della lista) viene chiamato ys.

      Se y è divisibile per 3 o per 5 (utilizzando l’operatore modulo: %) aggiungiamo il numero al risultato e poi eseguiamo la stessa funzione ricorsivamente per la coda della lista. In caso contrario, semplicemente saltiamo il valore di testa e continuiamo ad esaminare la coda della lista.

      Nell’8^ riga chiamiamo effettivamente la funzione sum_mul passando una lista come argomento. Questa lista è composta da tutti i numeri interi da 1 a 999 (o qualsiasi altro numero abbiate fissato come numero finale).

      Per eseguire il programma e visualizzare il risultato potete premere F5 come al solito (l’istruzione printfn stamperà il risultato in una finestra analoga al prompt di comandi), oppure potete evidenziare la porzione di codice da eseguire e premere contemporaneamente ALT + INVIO. In quest’ultimo caso, il programma sarà eseguito e il risultato sarà visibile nella finestra “F# interactive” che comparirà nella parte inferiore del video.

      La seconda soluzione invece è maggiormente ottimizzata:

      #light
      let sum_mult max step =
        let n = max / step
        step*n*(n + 1)/2
      
      let max = 999
      let sum2 = 
         sum_mult max 3 + sum_mult max 5 - sum_mult max 15
      printfn "%d" sum2

      Partendo dal presupposto che stiamo sommando tutti i multipli di 3 e di 5, possiamo anche effettuare una semplice operazione per trovare tutti i multipli dell’uno e dell’altro valore, invece di provare tutti i valori nell’intervallo considerato (da 1 a 999). In tal caso dobbiamo anche sottrarre tutti i multipli di 15, perché 15 è divisibile sia per 3 sia per 5, e quindi dobbiamo evitare di contare tali valori per due volte.

      Ricordando che la somma dei primi n numeri interi è uguale a n*(n+1)/2, possiamo utilizzare questa semplice formula per eseguire l’operazione desiderata, prima con il numero 3, poi con il numero 5 e infine con il numero 15.

      Nella 2^ linea definiamo la funzione sum_mult che prende due argomenti interi: max e step.

      Nella linea successiva, definiamo un identificatore locale denominato n, il cui ambito di visibilità è limitato all’interno della funzione sum_mult.

      Il resto del codice è estremamente semplice, dato che applichiamo la formula sopra indicata.

      Confrontando la complessità computazionale dei due programmi (chiamata “O grande”), troviamo che nel primo caso abbiamo una complessità O(n), mentre nel secondo caso abbiamo O(1). Nel secondo caso, quindi, la complessità (e la durata di esecuzione) è indipendente dal numero di valori da esaminare (in questo caso 999).

      N.B. lo spunto per questo post e l’informazione sul sito Project Euler .net è stato gentilmente concesso da Claudio Cherubino (http://www.fsharp.it e http://www.claudiocherubino.it/). Grazie!

      F# “tail”

      (Riporto questa discussione avvenuta la sera del 9 novembre 2010 sul forum dedicato a F#, nel portale di DotNetWork.it, poiché un problema al server l’ha purtroppo cancellata)

      Arcopal:
      Ciao e complimenti per il forum.
      Ho trovato in giro la seguente funzione:

      let rec length list = 
         match list with 
         | [] -> 0 
         | _ :: tail -> 1 + length tail

      Volevo capire come si interpreta. Specialmente l’ultima riga dove c’è la parola “tail”.

      Mia risposta:
      Ciao Arcopal.
      Partiamo dalla fine: la parola “tail” è in inglese e significa “coda” (così come “head” significa “testa”). Anzi, head e tail vengono utilizzati in particolare in algoritmi ricorsivi… Per esempio, proviamo a vedere questo codice che ho trovato in un libro su F#:

      // concatenate a list of strings 
      // into single string 
      let rec conactStringList = 
         function head :: tail -> head + conactStringList tail 
            | [] -> ""// test data 
      let jabber = 
         ["'Twas "; "brillig, "; "and ";
            "the "; "slithy "; "toves "; "..."] 
      // call the function 
      let completJabber = conactStringList jabber 
      // print the result 
      printfn "%s" completJabber

      Dovrebbe (in teoria) essere abbastanza chiaro che “head” indica il primo elemento di una lista, mentre “tail” indica la coda, cioè tutto il resto. Separando le due parti, diventa semplice gestire una lista di stringhe (come nell’esempio) con una funzione ricorsiva (che nel codice F# è indicata con la parola riservata “rec”). Riprendendo il codice che hai pubblicato tu e inserendo la parte del codice che ti ho appena fatto vedere, possiamo scrivere qualcosa come questo codice:

      let rec length list = 
         match list with 
            | [] -> 0 
            | _ :: tail -> 1 + length tail 
      // test data 
      let elenco = 
         ["'Twas "; "brillig, "; "and "; 
            "the "; "slithy "; "toves "; "..."] 
      // call the function 
      let l = length elenco

      Se avvii il programmino in F# interactive (selezionando tutto il codice di cui sopra e avviandolo con la combinazione ALT+INVIO), otterrai il seguente risultato:

      val length : 'a list -> int 
      val elenco : string list = 
         ["'Twas "; "brillig, "; "and "; 
            "the "; "slithy "; "toves "; "..."] 
      val l : int = 7

      F# in pillole: ancora stringhe

      Come in qualsiasi altro linguaggio di programmazione, una stringa è un gruppo di caratteri o simboli considerati come unica entità.

      Per inizializzare una stringa si può includere il suo valore tra doppi apici. Per esempio:

      let message = "Benvenuti nel mondo della programmazione funzionale!";

      Per visualizzare una variabile stringa utilizzando le funzioni printf o printfn, si può utilizzare %s come segnaposto della variabile. Ecco un esempio:

      let message = "Benvenuti nel mondo della programmazione funzionale!"
      printfn "%s" message;

      Dichiarando una variabile, se volete che sia proprio una stringa, potete utilizzare il tipo di dati string. Ecco un esempio:

      let message:string =
      "Benvenuti nel meraviglioso mondo della programmazione funzionale!"
      printfn "%s" message;

      Talvolta è necessario utilizzare una stringa il cui valore non è conosciuto in precedenza. Nessun problema: è possibile dichiarare prima una variabile stringa e poi utilizzare la variabile. Potete utilizzare le parole chiave “let” o “string” seguite dal nome della variabile che volete definire. Il nome deve rispettare le regole che abbiamo già indicato.

      Dichiarando una variabile stringa, è possibile inizializzarla con uno spazio vuoto, un carattere, un simbolo, una parola o un insieme di parole. Il valore fornito a una stringa deve essere incluso tra doppi apici. Per esempio:

      let nome = "Mario De Ghetto"
      let url = "http://books.deghetto.it"
      printfn "Benvenuti nel mondo della programmazione F#!"
      printfn "Nome: %s" nome
      printfn "URL: %s" url

      Questo codice produce il seguente risultato:

      > Benvenuti nel mondo della programmazione F#!
      Nome: Mario De Ghetto
      URL: http://books.deghetto.it
      val nome : string = "Mario De Ghetto"
      val url : string = “http://books.deghetto.it”

      Se si vuole dividere su più righe una stringa troppo lunga, è possibile tagliarla utilizzando un simbolo di “back slash” (“\”). Ecco un esempio

      printfn "Benvenuti nel mondo \
      della programmazione F#!"