Lukning (datalogi)

Inden for datalogi er en lukning en funktion, der har sit eget miljø. I dette miljø er der mindst én bundet variabel (et navn, der har en værdi, f.eks. et tal). Lukningens miljø opbevarer de bundne variabler i hukommelsen mellem lukningens brug.

Peter J. Landin gav denne idé navnet lukning i 1964. Programmeringssproget Scheme gjorde closures populære efter 1975. Mange programmeringssprog, der er udviklet efter denne tid, har closures.

Anonyme funktioner (funktioner uden navn) kaldes nogle gange fejlagtigt for closures. De fleste sprog, der har anonyme funktioner, har også closures. En anonym funktion er også en lukning, hvis den har sit eget miljø med mindst én bundet variabel. En anonym funktion uden eget miljø er ikke en lukning. En navngiven lukning er ikke anonym.

Lukninger og førsteklasses funktioner

Værdier kan være tal eller en anden type data, f.eks. bogstaver, eller datastrukturer, der består af enklere dele. I reglerne for et programmeringssprog er førsteklasses værdier værdier, der kan gives til funktioner, returneres af funktioner og bindes til et variabelnavn. Funktioner, der tager eller returnerer andre funktioner, kaldes funktioner af højere orden. De fleste sprog, der har funktioner som førsteklassesværdier, har også funktioner af højere orden og closures.

Se f.eks. på følgende Scheme-funktion:

; Returner en liste over alle bøger med mindst THRESHOLD solgte eksemplarer. (define (best-selling-books threshold) (filter (lambda (book) (>= (book-sales book) threshold)) book-list)))

I dette eksempel er lambda-udtrykket (lambda (book) (>= (book-sales book) threshold))) en del af funktionen best-selling-books. Når funktionen køres, skal Scheme lave værdien af lambdaen. Det gør det ved at lave en closure med koden for lambdaen og en henvisning til tærskelvariablen, som er en fri variabel inden for lambdaen. (En fri variabel er et navn, der ikke er bundet til en værdi).

Filterfunktionen kører derefter lukningen på hver bog på listen for at vælge, hvilke bøger der skal returneres. Da lukningen selv har en reference til tærskelværdien, kan lukningen bruge denne værdi, hver gang filteret kører lukningen. Selve filterfunktionen kan skrives i en helt separat fil.

Her er det samme eksempel omskrevet i ECMAScript (JavaScript), et andet populært sprog med understøttelse af closures:

// Returnerer en liste over alle bøger med mindst "tærskelværdi" solgte eksemplarer. function bestSellingBooks(tærskelværdi) { return bookList. filter( function(book) { return book. sales >= tærskelværdi; }     ); }

ECMAScript bruger ordet funktion her i stedet for lambda og Array.filter-metoden i stedet for filterfunktionen, men ellers gør koden det samme på samme måde.

En funktion kan oprette en lukning og returnere den. Følgende eksempel er en funktion, der returnerer en funktion.

I ordningen:

; Returner en funktion, der tilnærmer sig den afledte af f ; ved hjælp af et interval af dx, som skal være passende lille. (define (derivative f dx) (lambda (x) (/ (- (f (+ x dx))) (f x))) dx)))))

I ECMAScript:

// Returner en funktion, der tilnærmer sig den afledte af f // ved hjælp af et interval af dx, som skal være passende lille. function derivative(f, dx) { return function(x) { return (f(x + dx) - f(x)) / dx; }; }; }

Lukningsmiljøet beholder de bundne variabler f og dx, efter at den omsluttende funktion (afledning) vender tilbage. I sprog uden lukninger ville disse værdier gå tabt, når den omsluttende funktion vender tilbage. I sprog med lukninger skal en bundet variabel bevares i hukommelsen, så længe en lukning har den.

En lukning behøver ikke nødvendigvis at blive dannet ved hjælp af en anonym funktion. Programmeringssproget Python har f.eks. begrænset understøttelse af anonyme funktioner, men har lukninger. Ovenstående ECMAScript-eksempel kunne f.eks. implementeres i Python på følgende måde:

# Returner en funktion, der tilnærmer sig den afledte af f # ved hjælp af et interval af dx, som skal være passende lille. def derivative(f, dx): def gradient(x): return (f(x + dx) - f(x)) / dx return gradient

I dette eksempel danner funktionen gradient en lukning sammen med variablerne f og dx. Den ydre omsluttende funktion ved navn derivative returnerer denne lukning. I dette tilfælde ville en anonym funktion også fungere.

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

Python skal ofte bruge navngivne funktioner i stedet, fordi lambdaudtryk kun kan indeholde andre udtryk (kode, der returnerer en værdi) og ikke statements (kode, der har virkninger, men ingen værdi). Men i andre sprog, f.eks. i Scheme, returnerer al kode en værdi; i Scheme er alting et udtryk.

Anvendelse af lukninger

Lukninger har mange anvendelsesmuligheder:

  • Designere af softwarebiblioteker kan give brugerne mulighed for at tilpasse adfærd ved at sende lukninger som argumenter til vigtige funktioner. En funktion, der sorterer værdier, kan f.eks. acceptere et lukningsargument, der sammenligner de værdier, der skal sorteres, i henhold til et brugerdefineret kriterium.
  • Fordi lukninger udskyder evalueringen - dvs. at de ikke "gør" noget, før de bliver kaldt - kan de bruges til at definere kontrolstrukturer. F.eks. er alle Smalltalks standard kontrolstrukturer, herunder forgreninger (if/then/else) og sløjfer (while og for), defineret ved hjælp af objekter, hvis metoder accepterer closures. Brugere kan også nemt definere deres egne kontrolstrukturer.
  • Der kan produceres flere funktioner, der er tæt på det samme miljø, hvilket gør det muligt for dem at kommunikere privat ved at ændre dette miljø (i sprog, der tillader tildeling).

I ordningen

(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))) ; udskriver "none" (newline) (foo "meet me by the docks at midnight") (display (bar)) ; udskriver "meet me by the docks at midnight"
  • Lukninger kan bruges til at implementere objektsystemer.

Bemærk: Nogle talere kalder enhver datastruktur, der binder et leksikalsk miljø, for en lukning, men udtrykket henviser normalt specifikt til funktioner.

Spørgsmål og svar

Spørgsmål: Hvad er en afslutning i datalogi?


A: En closure er en funktion, der har sit eget miljø.

Spørgsmål: Hvad indeholder en closures miljø?


Svar: En closures miljø indeholder mindst én bundet variabel.

Spørgsmål: Hvem gav ideen om lukning sit navn?


Svar: Peter J. Landin gav navnet til lukningstanken i 1964.

Spørgsmål: Hvilket programmeringssprog gjorde closures populære efter 1975?


Svar: Programmeringssproget Scheme gjorde lukninger populære efter 1975.

Spørgsmål: Er anonyme funktioner og closures det samme?


Svar: Anonyme funktioner kaldes nogle gange fejlagtigt for closures, men ikke alle anonyme funktioner er closures.

Sp: Hvad gør en anonym funktion til en closure?


Svar: En anonym funktion er en lukning, hvis den har sit eget miljø med mindst én bundet variabel.

Sp: Er en navngiven lukning anonym?


Svar: Nej, en navngiven lukning er ikke anonym.

AlegsaOnline.com - 2020 / 2023 - License CC3