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:

; Restituisce un elenco di tutti i libri con almeno THRESHOLD copie vendute. (define (best-selling-books threshold) (filter (lambda (book) (>= (book-sales book) threshold))      book-list))

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:

// Restituisce un elenco di tutti i libri con almeno 'soglia' di copie vendute. function bestSellingBooks(soglia) { return bookList. filter( function(book) { return book. sales >= soglia; } ); }

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:

(definire (derivata f dx) (lambda (x) (/ (- (f (+ x dx)) (f x)) dx)))

In ECMAScript:

// restituisce una funzione che approssima la derivata di f // usando un intervallo di dx, che dovrebbe essere opportunamente piccolo. function derivative(f, dx) { return function(x) { return (f(x + dx) - f(x)) / dx; }; }

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 è:

# Restituisce una funzione che approssima la derivata di f # usando un intervallo di dx, che dovrebbe essere opportunamente piccolo. def derivata(f, dx): def gradiente(x): return (f(x + dx) - f(x)) / dx return gradiente

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.

def derivata(f, dx): return lambda x: (f(x + dx) - f(x)) / dx

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

(define foo #f) (define bar #f) (let ((secret-message "none")) (set! foo (lambda (msg) (set! secret-message msg)) (set! bar (lambda () secret-message)) (display (bar)) ; stampa "none" (newline) (foo "meet me by the docks at midnight") (display (bar)) ; stampa "meet me by the docks at midnight"
  • 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.

AlegsaOnline.com - 2020 / 2023 - License CC3