Le chiusure sono documentate in perlref.
Chiusura è un termine dell'informatica con un signficato preciso
ma difficile da spiegare. Le chiusure sono implementate in Perl come
subroutine anonime che conservano un riferimento persistente a variabili
lessicali non più visibili. Queste variabili lessicali, magicamente,
fanno riferimento alle variabili che erano visibili quando la subroutine
è stata definita (deep binding).
Le chiusure hanno senso in qualunque linguaggio di programmazione nel quale
il valore di ritorno di una funzione può essere esso stesso una
funzione, come in Perl. Notate che alcuni linguaggi mettono a disposizione
le funzioni anonime, ma non sono in grado di fornire chiusure effettive: il
Python, per esempio [1]. Per ulteriori informazioni sulle chiusure, fate
riferimento ad un qualunque libro sulla programmazione funzionale. Scheme
è un linguaggio che non solo supporta, ma incoraggia l'uso di chiusure.
Ecco una classica funzione che genera una funzione:
sub generatore_di_funzione_somma {
return sub { shift() + shift() };
}
$funzione_somma = generatore_di_funzione_somma();
$somma = $funzione_somma->(4,5); # $sum ora e` 9.
La chiusura funziona come un template di funzione con dello spazio lasciato libero
per la personalizzazione, da riempire in seguito. La subroutine anonima
restituita da generatore_di_funzione_somma() non è tecnicamente una
chiusura poichè non fa riferimento ad alcuna variabile lessicale non
più visibile.
Paragonate il caso precedente alla seguente funzione crea_sommatore(), nella
quale la funzione anonima che viene restituita contiene un riferimento ad una
variabile lessicale non visibile dalla funzione stessa. Questo riferimento
richiede che Perl restituisca un'opportuna chiusura, bloccando quindi per
sempre il valore che la variabile lessicale aveva quando la funzione è
stata creata.
sub crea_sommatore {
my $addendo = shift;
return sub { shift() + $addendo };
}
$f1 = crea_sommatore(20);
$f2 = crea_sommatore(555);
Ora &$f1($n) è sempre 20 più qualunque $n abbiate passato,
mentre &$f2($n) è sempre 555 più il valore passato.
Le chiusure sono usate spesso per scopi meno esoterici. Ad esempio, quando
volete passare un po' di codice ad una funzione:
my $linea;
timeout( 30, sub { $linea = <STDIN> } );
Se il codice fosse stato passato come stringa, '$linea = <STDIN'>, non
ci sarebbe stato alcun modo, per l'ipotetica funzione timeout(), di accedere
alla variabile lessicale $line visibile dal chiamante.
[1] NdT: questa nozione a proposito di Python non è più vera.
A partire dalla versione 2.2 si possono costruire chiusure con variabili
di sola lettura. Non conosco gli interpreti Python successivi. Per approfondimenti:
http://www.norvig.com/python-lisp.html
|