Închidere (programare)

Versiunea actuală a paginii nu a fost încă revizuită de colaboratori experimentați și poate diferi semnificativ de versiunea revizuită la 19 februarie 2015; verificările necesită 29 de modificări .

Închiderea ( eng.  closure ) în programare este o funcție de primă clasă , în corpul căreia există referințe la variabile declarate în afara corpului acestei funcții în codul înconjurător și care nu sunt parametrii acesteia. Într-o altă limbă, o închidere este o funcție care se referă la variabile libere din domeniul său .

O închidere, ca o instanță de obiect , este o modalitate de a reprezenta funcționalitatea și datele legate și împachetate împreună.

O închidere este un tip special de funcție. Este definită în corpul unei alte funcții și este creată de fiecare dată când este executată. Sintactic, aceasta arată ca o funcție care se află în întregime în corpul unei alte funcții. În acest caz, funcția interioară imbricată conține referințe la variabilele locale ale funcției exterioare. De fiecare dată când funcția exterioară este executată, este creată o nouă instanță a funcției interioare, cu noi referințe la variabilele funcției exterioare.

În cazul unei închideri, referințele la variabile dintr-o funcție exterioară sunt valabile în interiorul funcției imbricate atâta timp cât funcția imbricată rulează , chiar dacă funcția exterioară a terminat de rulat și variabilele au ieșit din domeniul de aplicare. [unu]

O închidere leagă codul unei funcții de mediul ei lexical (locul în care este definită în cod). Variabilele de închidere lexicale diferă de variabilele globale prin faptul că nu ocupă spațiul de nume global. Ele diferă de variabilele din obiecte prin faptul că sunt legate de funcții, nu de obiecte.

Exemple

Consultați wikibook pentru mai multe exemple.

În limba Scheme

( define ( make-adder n ) ; returnează o expresie lambda închisă ( lambda ( x ) ; unde x este o variabilă legată, ( + x n ) ; iar n este o expresie liberă (capturată din context extern) ) ) ( define add1 ( make-adder 1 )) ; faceți procedura de adăugare a 1 ( add1 10 ) ; sunați, întoarce 11 ( define sub1 ( make-adder -1 )) ; faceți o procedură pentru a scădea 1 ( sub1 10 ) ; sunați, întoarce 9

În JavaScript [2]

„utilizați strict” ; const add = function ( x ) { return function ( y ) { const z = x + y ; consola . log ( x + '+' + y + '=' + z ); întoarce z ; }; }; const res = add ( 3 )( 6 ); // returnează 9 și imprimă 3+6=9 în consolă consola . jurnal ( res );

Același cod în versiunea ECMAScript2015 folosind „funcții săgeți”:

„utilizați strict” ; const add = x => y => { const z = x + y ; consola . log ( x + '+' + y + '=' + z ); întoarce z ; }; const res = add ( 3 )( 6 ); // returnează 9 și imprimă 3+6=9 în consolă consola . jurnal ( res );

Explicație: în JavaScript, combinația => este un operator de declarare a funcției săgeată, vezi de exemplu https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions . Aici constanta add este plasată o funcție a argumentului x , al cărei rezultat va fi o altă funcție, și anume funcția argumentului y , al cărei rezultat este calculat de blocul de cod dat între paranteze. Acest bloc de cod se bazează pe argumentul y al funcției sale și pe o închidere care este creată pe argumentul x al funcției externe.

Când se apelează add(3)(6) , funcția stocată în variabila add este apelată cu un argument de 3 și returnează funcția legată la valoarea 3 din închiderea lui x .

Mai mult, în cadrul unui astfel de apel, această funcție este executată cu un argument y = 6 și returnează 9 .

Puteți face o închidere recursivă :

„utilizați strict” ; const add = x => y => { const z = x + y ; consola . log ( x + '+' + y + '=' + z ); returnează adăuga ( z ); }; const res = add ( 1 )( 4 )( 6 )( 9 ); consola . jurnal ( res ); /* 1+4=5 5+6=11 11+9=20 [Funcție]*/

Când codul JS rulează, variabilele locale sunt stocate în domeniu. În JavaScript, variabilele locale pot rămâne în memorie chiar și după ce funcția a returnat o valoare.

Toate funcțiile din JavaScript sunt închideri, adică ori de câte ori este creată o funcție, o închidere este întotdeauna creată, deși este adesea goală, deoarece funcțiile de obicei nu folosesc nimic din declarația contextului. Dar trebuie să înțelegeți diferența dintre crearea unei închideri și crearea unui nou obiect de domeniu: o închidere (funcție + referință la lanțul de domeniu curent) este creată atunci când funcția este definită, dar este creat un nou obiect de domeniu (și utilizat pentru a modifica lanțul domeniului de aplicare al închiderii) de fiecare dată când apelează funcția.

În PHP

În PHP, închiderile sunt funcții anonime , constructe speciale care vă permit să descrieți funcții care nu au nume specifice.

<?php function add ( $x ) { return function ( $y ) use ( $x ) { // <-- function (închidere) anonima return $x + $y ; }; // <-- acest punct și virgulă este necesar aici! } ecou adaugă ( 3 ) ( 5 ) . PHP_EOL ; // Ieșire: 8 $f = adaugă ( 3 ); var_dump ( $f ); // Ieșire: obiect(Închidere) echo $f ( 6 ) . PHP_EOL ; // Ieșire: 9

În PHP, variabilele sunt moștenite din domeniul părinte folosind constructul use prin specificarea explicită a numelor variabilelor moștenite.

Un alt exemplu de trecere a unei închideri la o metodă în care este așteptat un parametru apelabil:

<?php function power ( $arr , $exp ) { // $func va stoca o referinta la obiectul Closure care descrie inchiderea noastra $func = function ( $el ) use ( $exp ) { return $el ** $exp ; }; return array_map ( $func , $arr ); } $listă = [ 1 , 3 , 4 ]; var_dump ( putere ( $list , 2 )); // Ieșire: array(3) {[0]=>int(1) [1]=>int(9) [2]=>int(16)} var_dump ( putere ( $listă , 3 )); // Ieșire: array(3) {[0]=>int(1) [1]=>int(27) [2]=>int(64)}


Vezi și

Note

  1. Blocurile pot fi închideri - Containere, blocuri și iteratoare - Programming Ruby. Ghidul programatorului pragmatic. . Consultat la 29 septembrie 2011. Arhivat din original pe 23 septembrie 2011.
  2. Închidere: închiderea funcțiilor și stocarea datelor în domeniul de aplicare a funcției . — 08-01-2018. Arhivat din original pe 29 noiembrie 2019.