Linguaggi funzionali

Sono dei linguaggi di programmazione, che vietano il cambio di valore a una variabile. Un paio di esempi possono essere Scala o Erlang.

In questo tipo di linguaggi, una volta che il valore viene memorizzato, ci rimane per sempre. Se vogliamo memorizzare un altro valore, il linguaggio forza a creare una nuova variabile.

Stile imperativo

public class Esempio {
 
    // Approccio Imperativo
    public static Integer maxImperative(int[] numbers) {
        Integer max = null;
 
        if(numbers.length > 0) {
            max = numbers[0];
            for(int e : numbers) {
                if(e % 10 ==0 && e > max)
                    max = e;
            }
        }
 
        return max;
    }
 
    public static void main(String[] args) {
        int[] values = new int[] {2, 5, 6, 10, 8, 30, 150, 11, 100, 247, 45, 40, 132};
 
        System.out.println(Esempio.maxImperative(values));
 
    }
}

Siamo noi a dire COME fare per calcolare il max tra i multipli di 10, iterando nella lista, verificando le condizioni ecc… Quetsa implementazione sè pur giusta e funzionate può avere dei problemi:

Stile funzionale

// Approccio Funzionale
public static Integer maxFunctional(int[] numbers) {
  OptionalInt max = Arrays.stream(numbers)
                          .filter(number -> number % 10 == 0)
                          .max();
  // qui usiamo gli Optionals per verifcare se c'è un risultato
  return max.isPresent() ? max.getAsInt() : null;
}
 
public static void main(String[] args) { 
  int[] values = new int[] {2, 5, 6, 10, 8, 30, 150, 11, 100, 247, 45, 40, 132};
  System.out.println(Esempio.maxFunctional(values));      
}

L’approccio funzionale è di tipo dichiarativo. Nello stile dichiarativo ci si concentra sul COSA abbiamo bisogno e non sul COME ottenerlo (come si fà nella programmazione imperativa) e si delegano i dettagli a librerie di funzioni. Ne risulta uno stile conciso, espressivo, che non utilizza variabili spazzatura e non ha alcuna mutazione di variabili esplicita (nella nostra funzione max viene modificata una sola volta). In un ambiente multi-thread usando un codice con queste caratteristiche è molto più semplice gestire la concorrenza.

Ma il functional style nel nostro esempio entra in gioco con l’argomento passato al metodo filter:

Questa chiamata di funzione è molto diversa da quella a cui siamo abituati a vedere nelle versioni precedenti di linguaggi come Java e C. Invece di prendere valori o oggetti come argomento, questa funzione accetta come argomento una funzione anonima (una espressione lambda). Ciò rende questa funzione “funzionale nello stile”.

Nello stile funzionale si usano quelle che si chiamano funzioni di ordine superiore (high order function).

Le funzioni di ordine superiore possono:

Lo stile funzionale ha tutti i vantaggi dello stile dichiarativo e possiamo usare la scomposizione in funzioni come strumento di progettazione. Nella programmazione OO usiamo gli oggetti per modellare la separazione delle responsabilità. Con lo stile funzionale, deleghiamo diverse responsabilità a diverse funzioni.