Chiusura (informatica)
In informatica, una chiusura è una funzione che ha un proprio ambiente. In questo ambiente, c'è almeno una variabile vincolata (un nome che ha un valore, come un numero). L'ambiente della chiusura mantiene le variabili vincolate in memoria tra gli usi della chiusura.
Peter J. Landin diede a questa idea il nome di chiusura nel 1964. Il linguaggio di programmazione Scheme ha reso le chiusure popolari dopo il 1975. Molti linguaggi di programmazione realizzati dopo quel periodo hanno le chiusure.
Le funzioni anonime (funzioni senza nome) sono a volte erroneamente chiamate chiusure. La maggior parte dei linguaggi che hanno funzioni anonime hanno anche delle chiusure. Una funzione anonima è anche una chiusura se ha un proprio ambiente con almeno una variabile legata. Una funzione anonima senza un proprio ambiente non è una chiusura. Una chiusura con nome non è anonima.
Chiusure e funzioni di prima classe
I valori possono essere numeri o qualche altro tipo di dati, come le lettere, o strutture di dati composte da parti più semplici. Nelle regole di un linguaggio di programmazione, i valori di prima classe sono valori che possono essere dati alle funzioni, restituiti dalle funzioni e legati a un nome di variabile. Le funzioni che prendono o restituiscono altre funzioni sono chiamate funzioni di ordine superiore. La maggior parte dei linguaggi che hanno funzioni come valori di prima classe hanno anche funzioni di ordine superiore e chiusure.
Per esempio, date un'occhiata alla seguente funzione Scheme:
In questo esempio, l'espressione lambda (lambda (book) (>= (book-sales book) threshold))
fa parte della funzione best-selling-books.
Quando la funzione viene eseguita, Scheme deve rendere il valore della lambda. Lo fa creando una chiusura con il codice della lambda e un riferimento alla variabile soglia
, che è una variabile libera all'interno della lambda. (Una variabile libera è un nome che non è legato ad un valore).
La funzione filtro
esegue quindi la chiusura su ogni libro della lista per scegliere quali libri restituire. Poiché la chiusura stessa ha un riferimento alla soglia
, la chiusura può usare quel valore ogni volta che filter
esegue la chiusura. La funzione filtro
stessa potrebbe essere scritta in un file completamente separato.
Ecco lo stesso esempio riscritto in ECMAScript (JavaScript), un altro linguaggio popolare con supporto per le chiusure:
ECMAScript usa la parola function
qui invece di lambda
, e il metodo Array.filter al
posto della funzione filter
, ma per il resto il codice fa la stessa cosa nello stesso modo.
Una funzione può creare una chiusura e restituirla. L'esempio seguente è una funzione che restituisce una funzione.
In Schema:
In ECMAScript:
L'ambiente di chiusura mantiene le variabili vincolate f
e dx
dopo il ritorno della funzione di chiusura (derivata
). Nei linguaggi senza chiusure, questi valori verrebbero persi dopo il ritorno della funzione di chiusura. Nei linguaggi con le chiusure, una variabile vincolata deve essere mantenuta in memoria finché qualsiasi chiusura la possiede.
Una chiusura non deve necessariamente essere formata usando una funzione anonima. Il linguaggio di programmazione Python, per esempio, ha un supporto limitato per le funzioni anonime ma ha le chiusure. Per esempio, un modo in cui l'esempio ECMAScript di cui sopra potrebbe essere implementato in Python è:
In questo esempio, la funzione chiamata gradiente crea una chiusura insieme alle variabili f e dx. La funzione esterna chiusa chiamata derivata restituisce questa chiusura. In questo caso, funzionerebbe anche una funzione anonima.
Python deve spesso usare funzioni nominate invece perché le sue espressioni lambda possono contenere solo altre espressioni (codice che restituisce un valore) e non dichiarazioni (codice che ha effetti ma nessun valore). Ma in altri linguaggi, come Scheme, tutto il codice restituisce un valore; in Scheme, tutto è un'espressione.
Usi delle chiusure
Le chiusure hanno molti usi:
- I progettisti di librerie software possono permettere agli utenti di personalizzare il comportamento passando chiusure come argomenti a funzioni importanti. Per esempio, una funzione che ordina i valori può accettare un argomento di chiusura che confronta i valori da ordinare secondo un criterio definito dall'utente.
- Poiché le chiusure ritardano la valutazione - cioè, non "fanno" nulla finché non vengono chiamate - possono essere usate per definire strutture di controllo. Per esempio, tutte le strutture di controllo standard di Smalltalk, inclusi i rami (if/then/else) e i cicli (while e for), sono definiti usando oggetti i cui metodi accettano chiusure. Gli utenti possono facilmente definire anche le proprie strutture di controllo.
- Si possono produrre più funzioni che si chiudono sullo stesso ambiente, permettendo loro di comunicare privatamente alterando quell'ambiente (nei linguaggi che permettono l'assegnazione).
In Schema
- Le chiusure possono essere usate per implementare sistemi di oggetti.
Nota: Alcuni relatori chiamano qualsiasi struttura di dati che lega un ambiente lessicale una chiusura, ma il termine di solito si riferisce specificamente alle funzioni.
Domande e risposte
D: Che cos'è una chiusura in informatica?
R: Una chiusura è una funzione che ha un proprio ambiente.
D: Cosa contiene l'ambiente di una chiusura?
R: L'ambiente di una chiusura contiene almeno una variabile vincolata.
D: Chi ha dato il nome all'idea di chiusura?
R: Peter J. Landin ha dato il nome all'idea di chiusura nel 1964.
D: Quale linguaggio di programmazione ha reso le chiusure popolari dopo il 1975?
R: Il linguaggio di programmazione Scheme ha reso le chiusure popolari dopo il 1975.
D: Le funzioni anonime e le chiusure sono la stessa cosa?
R: Le funzioni anonime sono talvolta erroneamente chiamate chiusure, ma non tutte le funzioni anonime sono chiusure.
D: Cosa rende una funzione anonima una chiusura?
R: Una funzione anonima è una chiusura se ha un ambiente proprio con almeno una variabile vincolata.
D: Una chiusura con nome è anonima?
R: No, una chiusura con nome non è anonima.