martedì 20 agosto 2013

Funzioni "First Class" e "Higher Order" nella Programmazione Funzionale



In un recente post ho parlato della Programmazione Funzionale (FP) come di un paradigma di programmazione per computer che è sostanzialmente esente da side-effect, cioè a dirla in modo un po' brutale: è esente da comportamenti anomali a run-time.


In pratica, un programma scritto in FP pura si comporta come un foglio Excel. Si è mai visto un foglio Excel avere comportamenti anomali? Ci sono dei valori in input, ci sono delle formule e tutto quello che si ottiene sono dei valori di output che derivano dall'applicazione di quelle formule.

In modo simile, un programma FP è una funzione che prende come input una funzione - quindi, si potrebbe dire: una formula - e dà in output un certo risultato. A complicare le cose, c'è il fatto che una funzione FP solitamente prende in input una funzione che a sua volta prende in input una funzione e così via, fin quando ce ne sia bisogno per realizzare lo scopo del programma.

Per indicare questo tipo di comporamento, si dice che un generico linguaggio FP supporta le First Class Functions.

Una funzione, per essere "First Class", deve avere questa caratteristica: può essere passata ad un'altra funzione come qualsiasi altro valore.

Facciamo un esempio. (L'esempio in basso è scritto in linguaggio Scala, che è un linguaggio di programmazione che supporta molto bene il paradigma funzionale).


val areaDelCerchio = (raggio: Double) => { 
    raggio*raggio*Math.PI 
}
    
def printResult(result: Any) {
    println("L'area del cerchio e' : " + result.toString)
}
    
printResult( areaDelCerchio(10.0) )


La formula dell'area del cerchio viene memorizzata come valore (val). Questo basta per far sì che Scala possa dirsi un linguaggio dove le funzioni sono First Class, cioè vengono trattate come valori di prima classe, come lo sono solitamente gli interi o le stringhe. Significa che qualunque funzione può prendere come parametro un valore di prima classe: quindi, tipi elementari, oggetti e funzioni.

La funzione printResult è una funzione che si dice di ordine superiore, Higher Order Function, perché può prendere come parametro un qualsiasi valore e - anche! - una funzione.

Da un punto di vista di controllo dei tipi, la funzione/valore areaDelCerchio prende come parametro un Double (raggio, un valore decimale a doppia precisione) e ritorna un Double.

Qualsiasi oggetto in Scala - e quindi un Double, o una First Class Function - può essere convertito in Stringa. Ed ecco che printResult prende come parametro Any, cioè qualsiasi tipo o funzione, che possa essere rappresentato come stringa - che possegga il metodo .toString.

Poichè la funzione areaDelCerchio non mantiene variabili di stato e non accetta input dall'esterno che potrebbero modificarla, il suo comportamento è predicibile a priori ed esente da side-effect.

Una funzione Higher Order che prende come input tipi semplici o funzioni o funzioni di funzioni, ha un comportamento sempre predicibile e, una volta compilata, sarà esente da bug a run-time. Detto in altri termini: se un programma funzionale puro si compila - quindi non dà errori a compile-time - sarà esente da bug.

La capacità di esprimere un programma per computer, anche complesso, in termini di Higher Order Functions è dunque una garanzia che lo stesso, se si compila, avrà un comportamento predicibile e senza malfunzionamenti.

Se si pensa alle ingenti risorse che vengono impiegate normalmente in informatica per il test e il controllo della qualità del software, le implicazioni economiche di un simile approccio alla programmazione sono del tutto evidenti.


giovedì 7 marzo 2013

Programmazione asincrona in C# 5

C# versione 5 rende l'utilizzo della programmazione asincrona piuttosto agevole attraverso l'utilizzo di un pattern molto semplice e di due keyword: async e await.



Utilizzare codice "asincrono" è una necessità non solo quando si vuole parallelizzare l'esecuzione di procedure, ma anche quando si vuole rendere la logica di business indipendente dal codice che gestisce e muove l'interfaccia grafica. L'idea è che nessuna operazione debba "stoppare" l'esecuzione del codice deputato a gestire l'input dell'utente o a fornirgli un feedback.

Tanto più urgente è questa necessità quanto più il device ha processori poco potenti: che è il caso tipico dei device mobile. Ad esempio, il framework di programmazione di Windows Phone, WinRT, si basa pesantemente sul concetto di programmazione asincrona, ed il suo uso è obbligatorio. Non è possibile, giusto per citare un caso, in WinRTleggere un file in sincrono: è invece necessario predisporre il codice asincrono, in modo che mentre le operazioni di lettura del file sono in esecuzione, l'interfaccia e il resto del programma continuano a funzionare in parallelo.

La gestione della programmazione asincrona, benché semplice, è piuttosto controintuitiva. Su MSDN si legge che "l'operatore await dice al compilatore che il metodo marcato async non può continuare dopo quel punto fino a che il processo asincrono che si aspetta non è terminato". Cerchiamo di capire cosa significa con un esempio.

Supponiamo di avere una ipotetica funzione di business che ci impiega molto tempo per completare. Ad esempio questa, che su un portatile non troppo vecchio impiega qualche secondo:

static long LongRunningComputation(int i)
{
    Random cycleSeed = new Random();
    long result = 0; int rnd = 0;
    for (long j = 0; j < cycleSeed.Next() * 1E5 + 3E6; j++)
    {
        rnd = cycleSeed.Next(11);
        result += (rnd % 2 == 0) ? rnd : -rnd;
    }
    return result;
}

La prima cosa che occorre fare è incapsulare questa funzionalità in un metodo asincrono. Ogni metodo asincrono è tale se ritorna un oggetto Task. Un oggetto Task si costruisce con una Factory che si chiama Task.Run e prende in input una funzione lambda qualsiasi, con questa sintassi:

static async Task LongTaskAsync(int i)
{
    Task longOperation = 
            Task.Run(() > LongRunningComputation(i));

    return await longOperation;
}

La prima istruzione serve per costruire l'oggetto Task. Questo è un oggetto che mantiene lo stato e le informazioni sul processo asincrono che è in corso. Il fatto che la nostra operazione ritorni un intero viene riflesso nel fatto che Task è di fatto un contenitore generico (di un intero lungo).

La funzione lambda è in grado di "leggere" i parametri che sono in scope nel momento in cui è definita, quindi non c'è bisogno di specificare che intendiamo passargli l'intero "i" - questa cosa io ci ho messo francamente un po' per capirla... io avrei messo

((i) => LongRunningComputation(i))

 però il parametro di Task.Run è un delegato che non accetta parametri!

La norma vuole che ogni funzione "asincrona" abbia un nome che termina in "Async" e non ci adeguiamo. La parola "await" significa che questo metodo deve aspettare il termine dell'operazione "LongRunningComputation" prima di tornare un valore che abbia senso! Infatti il codice LongRunningComputation viene lanciato in asincrono, e quindi la linea di codice successiva viene eseguita immediatamente.

Senza la programmazione asincrona, si potrebbe pensare di costruire una funzione che esegue due chiamate all'operazione lunga e somma i loro risultati, così:

static long GoInLineNormally()
{
    Console.WriteLine("Going in sequence, normally");
    long x1 = LongRunningComputation(11);
    Console.WriteLine("X1 (NORMAL) = " + x1);
    long x2 = LongRunningComputation(22);
    Console.WriteLine("X2 (NORMAL) = " + x2);
    return (x1 + x2);
}

Siccome abbiamo detto che l'operazione lunga ci mette grossomodo due secondi, la procedura di cui sopra ci metterebbe circa quattro secondi per essere eseguita.

Ma abbiamo la programmazione asincrona, e quindi è lecito pensare che le due possano essere lanciate sue due thread differenti, e quando ciascun thread esce con un risultato, sommarli e stamparli a video.

static async Task GoInParallelAsync()
{
    Console.WriteLine("Going in parallel");

    var t1 = LongTaskAsync(11);
    var t2 = LongTaskAsync(22);

    await Task.WhenAll(t1, t2);

    Console.WriteLine("X1 (PARALLEL) = " + t1.Result);
    Console.WriteLine("X2 (PARALLEL) = " + t2.Result);
    return (t1.Result + t2.Result);
}


Per farlo abbiamo lanciato LongTaskAsync e poi, attraverso la funzione Task.WhenAll, abbiamo "aspettato" che entrambi finissero per raccogliere i risultati. L'esecuzione totale, come ci aspettavamo è di circa due secondi invece che quattro.

Ricapitolando. Se un metodo asincrono viene lanciato con l'operatore "await", l'esecuzione si ferma finché il metodo non ha ritornato un risultato - ma questo metodo viene comunque lanciato su un thread differente rispetto al programma che lo ha lanciato, il quale può ad esempio continuare così ad aggiornare l'interfaccia grafica e a rimanere in ascolto di eventuali eventi. Se invece un metodo asincrono viene lanciato senza l'operatore await, la linea successiva di codice viene eseguita immediatamente, e il controllo sull'esecuzione del task asincrono è demandato ai metodi della classe Task.

Infatti, se lanciamo con:

static async Task GoInLineAsync()
{
    Console.WriteLine("Going in sequence, but async");
    long x1 = await LongTaskAsync(11);
    Console.WriteLine("X1 (SEQUENCE) = " + x1);
    long x2 = await LongTaskAsync(22);
    Console.WriteLine("X2 (SEQUENCE) = " + x2);
    return (x1 + x2);
}


il codice esegue prima LongTaskAsync(11) e solamente dopo aver ottenuto il risultato (ciò che è espresso dall'operatore await), lancia il LongTaskAsync(22).

Questo codice, benché funzionalmente identico a GoInLineNormally è molto diverso dal punto di vista del comportamento! Il primo infatti è rigorosamente sincrono: ogni linea di codice viene eseguita solo e soltanto se quella precendente è terminata. Il secondo, invece, attraverso l'operatore "await" dice al compilatore: adesso esegui in asincrono su un thread differente LongTaskAsync, e aspetta che il metodo asincrono sia terminato prima di proseguire con la prossima linea di codice.

E' da notare in particolare il codice entry point, Main, che richiama le procedure scritte sopra:

static void Main(string[] args)
{
    Console.WriteLine("AYNC/AWAIT TEST v.1.0");
    Console.WriteLine();

    //long r = GoInLineNormally();
    var t = GoInLineAsync();
    //var t = GoInParallelAsync();

    Console.WriteLine("END TEST (Is it really ended?)");
    Console.WriteLine("Result = " + t.Result);
    Console.WriteLine();
    Console.ReadKey();

}

Domanda: quando viene stampata la linea "END TEST"?

Alla fine dell'esecuzione dei vari metodi GoIn...? La risposta è sì, se si tratta di GoInLineNormally(), ma è no in entrambi gli altri casi: si tratta di metodi asincroni che ritornano subito (non c'è await)! Quindi "END TEST" non è proprio un messaggio di End, perché viene stampato immediatamente, mentre i metodi asincroni sono in esecuzione. Viceversa, "Result =" viene stampato effettivamente alla fine dei calcoli, perché il valore di t è "awaited" da t.Result.

E se avessimo voluto "aspettare" l'esecuzione GoInLineAsync() prima di scrivere "END"? Non avremmo potuto farlo! Infatti un metodo che contiene una chiamata "await" deve per forza essere marcato "async". Ma il metodo Main non può essere "async"! Quindi non abbiamo potuto scrivere, per esempio:

var t = await GoInLineAsync()

Se avessimo marcato il metodo Main come "async", avremmo detto al compilatore che quel metodo va eseguito in asincrono e che deve ritornare immediatamente al chiamante, per poi "rientrare" quando il metodo sia terminato: due cose che un programma a console, evidentemente, non può fare.


giovedì 28 febbraio 2013

First Class Functions in Scala


A volte è necessario passare come argomenti dei metodi o delle funzioni non un parametro normale come un intero o una stringa, ma un'altra funzione. Ad esempio vorremmo scrivere un metodo che applica una somma o una moltiplicazione di due numeri, e vogliamo passargli come argomento la funzione "somma" o la funzione "moltiplicazione".

Un esempio meno banale: vorremmo scrivere una funzione di sorting che prende in input la collezione di oggetti da ordinare e l'algoritmo di sort. Questa funzione avrebbe quindi due parametri: la collezione e una funzione con l'implementazione dello specifico algoritmo.

Dunque vorremmo costruire una procedura che esegue una determinata operazione sui suoi parametri, e vorremmo passare come parametro l'operazione stessa, in modo da rendere la procedura del tutto generica, e perciò anche riutilizzabile.

Normalmente, nella programmazione orientata agli oggetti, questo si ottiene con un pattern che si chiama "Functor". Il Functor è un'interfaccia che espone un metodo che includerà la nostra funzione. Sta poi alla particolare implementazione dell'interfaccia stabilire se quella funzione è, ad esempio, una moltiplicazione o una somma.

Posto che in Scala le interfacce non esistono, ma esistono i "trait", di cui ho parlato in un altro post, si potrebbe pensare di scrivere due classi, Somma e Moltiplicazione, così fatte:

trait Functor {
  def function(x: Int, y: Int) : Int
}

class Somma extends Functor {
  def function(x: Int, y: Int) : Int = (x+y)
}

class Moltiplicazione extends Functor {
  def function(x: Int, y: Int) : Int = (x*y)
}

Cosa sono le "first class functions"? Sono una particolarità del linguaggio che ci permette di passare, come argomento di una funzione o di un metodo di classe, una funzione; esattamente quello che otteniamo con il pattern "Functor".

In questo caso però, noi non passiamo un oggetto che ha come metodo una specifica funzione: noi passiamo direttamente la funzione!

Questa è la sintassi da usare:

object FirstClassFunctions {
  val somma = (x: Int, y: Int) => (x+y)
  val moltiplicazione = (x: Int, y: Int) => (x*y)
}


La variabile "somma" non è né un tipo primitivo (intero o stringa, ad esempio), nè un oggetto. E' una funzione. La prima parte dice quali sono i tipi che la funzione manipola, e la seconda parte è la funzione vera e propria. Somma è una funzione che somma il valore x al valore y. Similmente per moltiplicazione.


object Main {

  // Functor
  val functSomma : Functor = new Somma()
  val functMoltiplicazione : Functor = new Moltiplicazione()

  def testFunctor(f:Functor, x:Int, y:Int) {
    println("Il risultato e' = " + f.function(x,y))
  }

  // First Class
  def testFirstClass(f: (Int,Int) => Int, x:Int, y:Int)  {
    println("Il risultato e' = %d".format(f(x,y)))
  }


  // Main
  def main(args: Array[String]) {

    testFunctor(functSomma, 6, 5)
    testFunctor(functMoltiplicazione, 6, 5)

    testFirstClass(FirstClassFunctions.somma, 6, 5)
    testFirstClass(FirstClassFunctions.moltiplicazione, 6, 5)

  }

}


Il codice di sopra richiama le funzioni sia sotto forma di Functor, che sotto forma di First Class Functions.
Com'è ovvio, la possibilità di passare direttamente funzioni come parametri di metodi, piuttosto che inventare una tassonomia apposita di classi, riduce la complessità del codice, aumenta la leggibilità e quindi in definitiva migliora la qualità del codice sorgente.


venerdì 8 febbraio 2013

Aiuto mi sono scomparsi i favoriti!


E' possibile che dal menù di apertura o salvataggio dei file in Windows 8 scompaia la selezione delle locazioni preferite, in inglese "Favourites", nella barra a sinistra, altrimenti detta "Places Bar"

Tra queste locazioni ci sono normalmente il Desktop, i Download e i Recent Places, in più lo shortcut è facilmente personalizzabile facendo drag'n'drop del folder che vogliamo aggiungere.

Pochi però sanno che è possibile eliminare i Favourites, anche inavvertitamente, spuntando l'opzione "Mostra Preferiti" della Places Bar.


Per ripristinarli, basta spostarsi in basso nella Places Bar e selezionare "Mostra Preferiti" (Show Favourites).