Stängning (programmering)

Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från versionen som granskades den 19 februari 2015; kontroller kräver 29 redigeringar .

Closure ( eng.  closure ) i programmering är en förstklassig funktion , i vars brödtext det finns referenser till variabler som deklareras utanför kroppen av denna funktion i den omgivande koden och som inte är dess parametrar. På ett annat språk är en stängning en funktion som refererar till fria variabler i dess omfattning .

En stängning, som en objektinstans , är ett sätt att representera funktionalitet och data bundna och paketerade tillsammans.

En stängning är en speciell typ av funktion. Den definieras i kroppen för en annan funktion och skapas varje gång den exekveras. Syntaktiskt ser detta ut som en funktion som är helt och hållet i kroppen av en annan funktion. I det här fallet innehåller den kapslade inre funktionen referenser till de lokala variablerna för den yttre funktionen. Varje gång den yttre funktionen exekveras skapas en ny instans av den inre funktionen, med nya referenser till variablerna för den yttre funktionen.

I fallet med en stängning är referenser till variabler i en yttre funktion giltiga inuti den kapslade funktionen så länge den kapslade funktionen körs , även om den yttre funktionen har körts färdigt och variablerna har gått utanför räckvidden. [ett]

En stängning länkar koden för en funktion till dess lexikala miljö (den plats där den definieras i koden). Lexikaliska stängningsvariabler skiljer sig från globala variabler genom att de inte upptar den globala namnrymden. De skiljer sig från variabler i objekt genom att de är bundna till funktioner, inte objekt.

Exempel

Se wikiboken för fler exempel.

schemaspråket

( define ( make-adder n ) ; returnerar ett slutet lambdauttryck ( lambda ( x ) ; där x är en bunden variabel, ( + x n ) ; och n är en fri (fångad från extern kontext) ) ) ( definiera add1 ( make-adder 1 )) ; gör proceduren för att lägga till 1 ( lägg till1 10 ) ; kalla det, returnerar 11 ( definiera sub1 ( make-adder -1 )) ; gör en procedur för att subtrahera 1 ( sub1 10 ) ; kalla det, returnerar 9

I JavaScript [2]

'använd strikt' ; const add = function ( x ) { return function ( y ) { const z = x + y ; konsol . log ( x + '+' + y + '=' + z ); returnera z ; }; }; const res = addera ( 3 )( 6 ); // returnerar 9 och skriver ut 3+6=9 till konsolen konsol . log ( res );

Samma kod i ECMAScript2015-versionen med "pilfunktioner":

'använd strikt' ; const add = x => y => { const z = x + y ; konsol . log ( x + '+' + y + '=' + z ); returnera z ; }; const res = addera ( 3 )( 6 ); // returnerar 9 och skriver ut 3+6=9 till konsolen konsol . log ( res );

Förklaring: i JavaScript är kombinationen => en pilfunktionsdeklarationsoperator, se till exempel https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions . Här placeras den konstanta adderingen en funktion av argumentet x , vars resultat blir en annan funktion, nämligen funktionen av argumentet y , vars resultat beräknas av kodblocket inom parentes. Detta kodblock förlitar sig på y -argumentet för dess funktion och på en stängning som skapas på x -argumentet för den yttre funktionen.

När add(3)(6) anropas anropas funktionen som är lagrad i variabeln add med argumentet 3 och returnerar funktionen bunden till värdet 3 i x 's closure .

Vidare, inom ramen för ett sådant anrop, exekveras denna funktion med ett argument y = 6 och returnerar 9 .

Du kan göra en rekursiv stängning:

'använd strikt' ; const add = x => y => { const z = x + y ; konsol . log ( x + '+' + y + '=' + z ); returnera add ( z ); }; const res = addera ( 1 )( 4 )( 6 )( 9 ); konsol . log ( res ); /* 1+4=5 5+6=11 11+9=20 [Funktion]*/

När JS-koden körs lagras lokala variabler i scope. I JavaScript kan lokala variabler finnas kvar i minnet även efter att funktionen har returnerat ett värde.

Alla funktioner i JavaScript är stängningar, det vill säga när en funktion skapas skapas alltid en stängning, även om den ofta är tom, eftersom funktioner vanligtvis inte använder något från kontextdeklarationen. Men du måste förstå skillnaden mellan att skapa en stängning och att skapa ett nytt scope-objekt: en stängning (funktion + referens till den aktuella scope-kedjan) skapas när funktionen definieras, men ett nytt scope-objekt skapas (och används för att ändra stängningens omfattningskedja) varje gång funktionsanrop.

I PHP

I PHP är stängningar anonyma funktioner , speciella konstruktioner som låter dig beskriva funktioner som inte har specifika namn.

<?php function add ( $x ) { return function ( $y ) use ( $x ) { // <-- anonym funktion (closure) return $x + $y ; }; // <-- detta semikolon behövs här! } echo add ( 3 ) ( 5 ) . PHP_EOL ; // Utdata: 8 $f = lägg till ( 3 ); var_dump ( $f ); // Output: object(Closure) echo $f ( 6 ) . PHP_EOL ; // Utdata: 9

I PHP ärvs variabler från det överordnade omfånget med användningskonstruktionen genom att explicit specificera namnen på de ärvda variablerna.

Ett annat exempel på att skicka en stängning till en metod där en anropsbar parameter förväntas:

<?php function power ( $arr , $exp ) { // $func kommer att lagra en referens till Closure-objektet som beskriver vår stängning $func = function ( $el ) use ( $exp ) { retur $el ** $exp ; }; returnera array_map ( $func , $arr ); } $list = [ 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 )); // Utdata: array(3) {[0]=>int(1) [1]=>int(27) [2]=>int(64)}


Se även

Anteckningar

  1. Block kan vara förslutningar - Behållare, block och iteratorer - Programmering Ruby. Den pragmatiska programmerarens guide. . Hämtad 29 september 2011. Arkiverad från originalet 23 september 2011.
  2. Stängning: Funktionsstängningar och lagring av data i funktionsomfång . — 2018-01-08. Arkiverad från originalet den 29 november 2019.