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).