Lukning (programmering)

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 19. februar 2015; checks kræver 29 redigeringer .

Lukning ( eng.  closure ) i programmering er en førsteklasses funktion , i hvis krop der er referencer til variabler erklæret uden for denne funktions krop i den omgivende kode, og som ikke er dens parametre. På et andet sprog er en lukning en funktion, der refererer til frie variabler i dens omfang .

En lukning er ligesom en objektinstans en måde at repræsentere funktionalitet og data bundet og pakket sammen på.

En lukning er en særlig form for funktion. Den er defineret i en anden funktions krop og oprettes hver gang den udføres. Syntaktisk ligner dette en funktion, der er helt inde i en anden funktions krop. I dette tilfælde indeholder den indlejrede indre funktion referencer til de lokale variabler for den ydre funktion. Hver gang den ydre funktion udføres, oprettes en ny instans af den indre funktion med nye referencer til variablerne i den ydre funktion.

I tilfælde af en lukning er referencer til variabler i en ydre funktion gyldige inde i den indlejrede funktion, så længe den indlejrede funktion kører , selvom den ydre funktion er færdig med at køre, og variablerne er gået uden for scope. [en]

En lukning forbinder koden for en funktion til dens leksikalske miljø (det sted, hvor den er defineret i koden). Leksikalske lukkevariabler adskiller sig fra globale variabler ved, at de ikke optager det globale navneområde. De adskiller sig fra variabler i objekter ved, at de er bundet til funktioner, ikke objekter.

Eksempler

Se wikibogen for flere eksempler.

skemasproget

( definer ( make-adder n ) ; returnerer et lukket lambda-udtryk ( lambda ( x ) ; hvor x er en bundet variabel, ( + x n ) ; og n er en fri (fanget fra ekstern kontekst) ) ) ( definer add1 ( make-adder 1 )) ; udfør proceduren for at tilføje 1 ( tilføj1 10 ) ; kald det, returnerer 11 ( definer sub1 ( make-adder -1 )) ; udføre en procedure for at trække 1 ( sub1 10 ) fra ; kald det, returnerer 9

I JavaScript [2]

'brug streng' ; const add = funktion ( x ) { return funktion ( y ) { const z = x + y ; konsol . log ( x + '+' + y + '=' + z ); returnere z ; }; }; const res = add ( 3 )( 6 ); // returnerer 9 og udskriver 3+6=9 til konsollen konsol . log ( res );

Den samme kode i ECMAScript2015-versionen ved hjælp af "pilefunktioner":

'brug streng' ; const add = x => y => { const z = x + y ; konsol . log ( x + '+' + y + '=' + z ); returnere z ; }; const res = add ( 3 )( 6 ); // returnerer 9 og udskriver 3+6=9 til konsollen konsol . log ( res );

Forklaring: i JavaScript er kombinationen => en pilefunktionserklæringsoperator, se for eksempel https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions . Her placeres konstant add en funktion af argumentet x , hvis resultat vil være en anden funktion, nemlig funktionen af ​​argumentet y , hvis resultat beregnes af kodeblokken angivet i krøllede parenteser. Denne kodeblok er afhængig af y -argumentet for dens funktion og på en lukning, der er oprettet på x -argumentet for den ydre funktion.

Når add(3)(6) kaldes, kaldes funktionen gemt i variablen add med et argument på 3 og returnerer funktionen bundet til værdien 3 i x 's lukning .

Yderligere, inden for rammerne af et sådant kald, udføres denne funktion med et argument y = 6 og returnerer 9 .

Du kan lave en rekursiv lukning:

'brug streng' ; const add = x => y => { const z = x + y ; konsol . log ( x + '+' + y + '=' + z ); returnere tilføje ( z ); }; const res = add ( 1 )( 4 )( 6 )( 9 ); konsol . log ( res ); /* 1+4=5 5+6=11 11+9=20 [Funktion]*/

Når JS-koden kører, gemmes lokale variabler i scope. I JavaScript kan lokale variabler forblive i hukommelsen, selv efter funktionen har returneret en værdi.

Alle funktioner i JavaScript er lukninger, det vil sige, når en funktion oprettes, oprettes der altid en lukning, selvom den ofte er tom, da funktioner normalt ikke bruger noget fra kontekstdeklarationen. Men du skal forstå forskellen mellem at oprette en lukning og oprettelse af et nyt omfangsobjekt: en lukning (funktion + reference til den aktuelle omfangskæde) oprettes, når funktionen er defineret, men et nyt omfangsobjekt oprettes (og bruges til at ændre lukningens omfangskæde) hver gang funktionskald.

I PHP

I PHP er lukninger anonyme funktioner , specielle konstruktioner, der giver dig mulighed for at beskrive funktioner, der ikke har specifikke navne.

<?php function add ( $x ) { return function ( $y ) use ( $x ) { // <-- anonym funktion (closure) return $x + $y ; }; // <-- dette semikolon er nødvendigt her! } ekko tilføje ( 3 ) ( 5 ) . PHP_EOL ; // Output: 8 $f = tilføje ( 3 ); var_dump ( $f ); // Output: object(Closure) echo $f ( 6 ) . PHP_EOL ; // Output: 9

I PHP nedarves variabler fra det overordnede omfang ved hjælp af brugskonstruktionen ved eksplicit at angive navnene på de nedarvede variable.

Et andet eksempel på at overføre en lukning til en metode, hvor en parameter, der kan kaldes, forventes:

<?php function power ( $arr , $exp ) { // $func vil gemme en reference til Closure-objektet, der beskriver vores closure $func = function ( $el ) use ( $exp ) { retur $el ** $exp ; }; returner array_map ( $func , $arr ); } $liste = [ 1 , 3 , 4 ]; var_dump ( power ( $list , 2 )); // Output: array(3) {[0]=>int(1) [1]=>int(9) [2]=>int(16)} var_dump ( power ( $list , 3 )); // Output: array(3) {[0]=>int(1) [1]=>int(27) [2]=>int(64)}


Se også

Noter

  1. Blokke kan være lukninger - containere, blokke og iteratorer - programmering af rubin. Den pragmatiske programmørvejledning. . Hentet 29. september 2011. Arkiveret fra originalen 23. september 2011.
  2. Lukning: Funktionslukninger og lagring af data i funktionsomfang . - 2018-01-08. Arkiveret fra originalen den 29. november 2019.