Una tecnica molto comune nell'ambito della programmazione funzionale è l'applicazione parziale di una funzione. Per applicazione parziale intendiamo l'applicazione di una funzione che accetta n argomenti, ad un numero di argomenti inferiore, ottenendo così una nuova funzione specializzata.
Nell'ambito funzionale, il numero di argomenti di una funzione è detto arietà (arity). Quindi, da un punto di vista formale, possiamo dire che l'applicazione parziale è una tecnica che consente di ridurre l'arietà di una funzione.
Proviamo a spiegare questa tecnica con un esempio. Supponiamo di avere la funzione somma()
descritta dal seguente codice:
function somma(x, y) {
return x + y;
}
Come risulta evidente, questa funzione prevede due argomenti e restituisce la loro somma. Consideriamo ora la seguente definizione di funzione:
function incrementa(x) {
return somma(1, x);
}
La funzione incrementa()
è il risultato dell'applicazione parziale della funzione somma()
. In altre parole, la funzione incrementa()
è una funzione specializzata nella somma di 1 al suo secondo parametro. All'atto pratico, la funzione incrementa()
equivale alla funzione somma()
con un numero ridotto di argomenti, dal momento che il primo argomento viene fissato a 1.
Anche se a prima vista la tecnica di applicazione parziale di una funzione può sembrare un esercizio teorico, essa ha in realtà un risvolto pratico molto interessante, dal momento che essa viene generalmente considerata la versione funzionale della dependency injection.
Immaginiamo una funzione che consente di effettuare una certa elaborazione di dati la cui firma è definita come segue:
function elabora(dati, logger) {
...
}
Questa funzione prevede anche la possibilità di creare un log dell'elaborazione, ma la modalità di generazione del log può dipendere dall'applicazione in cui essa verrà utilizzata. Quello che verosimilmente accade è che in fase di inizializzazione dell'applicazione possiamo definire una funzione effettuando l'applicazione parziale della funzione elabora()
, come mostrato di seguito:
function elaboraConLog(dati) {
let logger = new Logger();
return elabora(dati, logger);
}
A questo punto all'interno dell'applicazione basterà chiamare semplicemente la funzione elaboraConLog()
, cioè la versione specializzata della funzione elabora()
.