Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Operazioni sulle funzioni

L'uso della programmazione funzionale in Javascript è spesso basata sulla composizione di funzioni: ecco alcune considerazioni in merito a tali operazioni.
L'uso della programmazione funzionale in Javascript è spesso basata sulla composizione di funzioni: ecco alcune considerazioni in merito a tali operazioni.
Link copiato negli appunti

Il concetto di trasparenza referenziale introdotto nelle lezioni precedenti può sembrare scontato, quasi ovvio. Eppure esso è alla base di numerose applicazioni nell'ambito della programmazione funzionale. Esso ci garantisce che è possibile sostituire espressioni con i relativi valori risultanti senza modificare la semantica di un'applicazione. Applicando questo principio, possiamo effettuare una serie di operazioni sulle funzioni che ci consentono di ottenere una maggiore espressività nella scrittura del codice ed una sua maggiore riusabilità. Vediamo quali sono le tecniche più comuni che sfruttano questo principio.

Composizione di funzioni

In qualità di sviluppatori, abbiamo sicuramente già sfruttato in un significativo numero di occasioni la composizione di funzioni. Magari senza rendercene conto o senza dargli troppo peso, abbiamo certamente utilizzato il risultato di una funzione per assegnarlo come valore di input ad un'altra funzione. È questo in effetti il concetto di composizione di una funzione.

In maniera un po' più formale, possiamo dire che la composizione di funzioni è la combinazione di due o più funzioni per creare una nuova funzione.

In termini matematici, la composizione di funzioni viene rappresentata tramite l'operatore di composizione . Se ad esempio abbiamo le funzioni f(x) e g(x), la loro composizione viene indicata come fᵒg e corrisponde all'espressione f(g(x)). In pratica, possiamo definire una nuova funzione h = fᵒg e scrivere h(x) ottenendo lo stesso risultato di f(g(x)).

Proviamo a spiegare il concetto con un esempio concreto. Supponiamo di avere una funzione che, data una stringa restituisca un array di parole, cioè di sottostringhe delimitate da spazi:

function split(string) {
   return string.split(" ");
}

Abbiamo definito la funzione split() sfruttando l'omonimo metodo delle stringhe JavaScript. Questa definizione può sembrare ridondante, dal momento che potremmo utilizzare direttamente il metodo delle stringhe. Ma è utile utilizzare la notazione funzionale per spiegare il concetto di composizione.

Definiamo ora una funzione che inverte l'ordine degli elementi di un array, come la seguente:

function reverse(array) {
   return array.reverse();
}

Anche in questo caso abbiamo sfruttato un metodo esistente: il metodo reverse() degli array.

Infine definiamo la funzione join() che restituisce una stringa composta dalla concatenazione degli elementi di un array di stringhe separandole con spazi:

function join(array) {
   return array.join()
}

Queste tre funzioni possono essere composte insieme dando origine ad una nuova funzione. La seguente è la definzione di una funzione derivata dalla composizione delle tre funzioni appena definite e che restituisce una nuova stringa il cui ordine delle parole risulta invertito:

function reverseString(string) {
   return join(reverse(split(string)));
}

Questa nuova funzione è il risultato della composizione matematica joinᵒreverseᵒsplit. Possiamo esprimere la funzione
reverseString() in forma più compatta sfruttando la sintassi delle arrow function, come nel seguente esempio:

const reverseString = (string) => join(reverse(split(string)))

In ogni caso, abbiamo definito una nuova funzione componendo funzioni esistenti.

L'utilizzo della composizione di funzioni consente di definire operazioni semplici, quindi più facilmente controllabili e testabili, e di costruire con esse operazioni più complesse. Si tratta, in pratica, dell'applicazione del principio di singola responsabilità applicato al mondo funzionale. Creando funzioni focalizzate su una specifica responsabilità, ne limitiamo la complessità e favoriamo il riuso del codice. In altre parole, possiamo creare funzioni più complesse componendo funzioni semplici.

Ti consigliamo anche