Închidere (computer)

De la Wikipedia, enciclopedia liberă.
Salt la navigare Salt la căutare

În limbaje de programare , o închidere este o abstracție care combină o funcție cu variabilele libere prezente în mediul în care este definită în conformitate cu regulile de aplicare a limbajului. Variabilele de mediu libere rămân accesibile pe toată durata închiderii și, prin urmare, persistă în timpul invocațiilor ulterioare ale închiderii. În consecință, variabilele de închidere pot fi utilizate pentru a menține starea și a emula constructele de programare orientate pe obiecte .

Închiderile sunt utile atunci când o funcție trebuie să „amintească” informații: de exemplu un parametru specific pentru o operațiune de comparație sau referința la un widget într-un apel invers al unei interfețe grafice.

Teorie și implementare

Închiderile, de obicei, sunt implementate cu o structură specială de date care conține un pointer către codul funcției și o reprezentare a mediului lexical al acestuia în momentul creării sale (de exemplu, setul de variabile disponibile și valorile lor).

Implementarea variabilelor libere legate într-o închidere necesită un tratament diferit de variabilele normale pe care multe limbi le mențin într-o stivă liniară. De fapt, stiva este eliberată la întoarcerea dintr-o invocație, în timp ce variabilele libere ale unei închideri trebuie să supraviețuiască. Prin urmare, aceste variabile trebuie alocate diferit pentru a persista până când nu mai sunt utilizabile. Prin urmare, de obicei variabilele închiderii sunt alocate în grămadă și colectarea gunoiului este utilizată pentru a aloca închiderea. Acest lucru explică de ce închiderile se găsesc de obicei în limbile de colectare a gunoiului .

Conceptul de închidere poate fi legat de cel al actorilor din modelul actorului în calculul simultan , unde valorile variabilelor din mediul lexical al funcției sunt numite cunoscuți ai actorului . O întrebare importantă despre închiderile în limbaje de paradigmă concurente este dacă variabilele unei închideri pot fi actualizate și, dacă da, cum pot fi sincronizate aceste modificări. Actorii reprezintă o soluție la această problemă [1] .

Închideri și funcții

Închiderile sunt prezente în acele limbaje care tratează funcțiile ca obiecte de primă clasă (obiect de primă clasă), care vă permit să le transmiteți ca parametri către alte funcții, să le returnați ca valori de la alte funcții, să le atribuiți variabilelor etc., Cum te simți cu tipuri mai simple, cum ar fi șiruri , numere întregi etc.

În ML , următorul cod definește o funcție f care returnează parametrul trecut la acesta plus 1:

 fun f ( x ) = x + 1 ;

Dacă o funcție folosește variabile libere, adică non-locale, atunci când este definită, se creează o închidere care captează aceste variabile. De exemplu, în acest fragment de cod:

 val y = 1 ;
fun f ( x ) = x + y ;

structura de date de închidere reprezentând f conține o referință la variabila y prezentă în mediul de definiție, unde este legată de valoarea 1. Deoarece în ML valoarea lui y nu poate modifica comportamentul lui f nu se schimbă. Pe de altă parte, dacă se utilizează o variabilă alocabilă, f returnează valoarea parametrului său adăugată la valoarea y în momentul în care este apelată. De exemplu:

 val y = ref 1 ;
lasa f (x) = x +! y ;
f ( 3 );
y : = 5 ;
f ( 3 );

Primul apel al lui f 3 returnează 4, al doilea returnează 8.

Pentru a clarifica rolul mediului lexical, luați în considerare următorul fragment din ML :

 lăsa
  val y = 1 ;
  fun f ( x ) = x + y ;
în
  lăsa
    val y = 2 ;
  în
    f ( 3 )
  Sfârșit
Sfârșit

în acest exemplu , există două variabile diferite , cu același nume y , care a exterior let , unde este 1, și cea a cel mai interior let , în cazul în care acesta este 2. închidere f este creat în mediul exterior, și , prin urmare , nu referindu-ne la y cu valoarea 1 și din acest motiv, rezultatul obținut este 4, nu 5.

Utilizări ale închiderilor

Închiderile au multe utilizări:

  • Acestea pot fi utilizate pentru a crește abstracția și versatilitatea unor funcții. De exemplu, o funcție pentru sortarea unei liste de valori poate accepta o închidere ca parametru, care compară două valori pentru a fi sortate în funcție de un criteriu definit de utilizator.
  • Deoarece o închidere își amână evaluarea (adică „nu” face nimic până când nu este invocată), poate fi utilizată pentru a defini structurile de control . De exemplu, toate structurile de control Smalltalk standard, inclusiv cele condiționale (if / then / else) și buclele (while și for), sunt definite folosind obiecte ale căror metode acceptă închideri. Astfel, programatorii pot scrie și noi structuri de control.
  • Pot fi implementate mai multe funcții care „închid” același mediu, permițându-le să comunice privat modificând mediul pe care îl partajează.

Notă: Închiderile sunt denumite uneori și structuri de date care combină un mediu lexical cu entități care nu sunt funcții, dar totuși termenul se referă în mod specific la funcții.

Limbaje de programare cu închideri

Schema a fost primul limbaj de programare care a avut închideri de amploare complet generale și lexicale. Practic toate limbajele de programare funcționale și toate limbajele de programare orientate obiect derivate din Smalltalk acceptă o formă de închidere. Unele dintre limbajele de programare majore pentru a sprijini închiderile sunt:

Simulează închiderile

În C, puteți utiliza cuvântul cheie „static” înainte de a declara o variabilă locală. O variabilă statică își păstrează valoarea prin diferite apeluri către funcție. Acest lucru este valabil și pentru C ++ .

 funcția int ( int arg )
{
  static int numOfCalls = 0 ;
  static struct State infoOnStatus ;
  returnează ++ numOfCalls ;
}

Unele limbaje orientate către obiecte permit programatorului să utilizeze obiecte care simulează unele caracteristici ale închiderilor. De exemplu:

  • Java permite programatorului să definească „ clase anonime” în cadrul unei metode ; o clasă anonimă se poate referi la numele declarate în clasele în care este închisă și la numele obiectelor de tip final declarate în metoda în care este închisă.
 interfață publică Funcție < De la , la >
{
  O aplicație ( dintr-un parametru );
}
// alte...
public final Function < Integer , Integer > createSummer ( final int x )
{
   returnează funcția nouă < Număr întreg , întreg > ()
   {
      public Integer apply ( Integer unParameter )
      {
        returnează x + aParameter ;
      }
   };
}
// alte...

(Rețineți că acest exemplu folosește aspecte ale limbajului disponibile numai din versiunea Java 1.5 / 5.0 , cum ar fi generice , autoboxing și autounboxing )

  • În C ++ și D , programatorii pot defini clase care supraîncarcă operatorul () (operator de aplicație funcțională). Aceste tipuri de clase sunt numite obiecte funcționale sau, ocazional, functori (deși acesta din urmă termenul este ambiguu, deoarece în alte limbi are un sens foarte diferit). Aceste obiecte funcționale se comportă similar cu funcțiile din limbajele de programare funcționale, dar sunt diferite de închideri prin faptul că variabilele din mediul lor nu sunt „capturate”. Pentru a simula o închidere adevărată, vă puteți imagina punând toate variabilele globale într-o singură structură ( struct ) și trecând o copie a acestora unui obiect funcțional.
  • C # permite unui delegat ( delegate ) să stocheze o referință la o metodă a unei instanțe a unei clase (adică un obiect); când este apelat acest delegat, metoda va fi invocată pentru acea instanță specială. Pentru a simula o închidere adevărată, puteți crea o instanță a unei clase (adică un obiect) cu atributele necesare. O altă modalitate de a simula închiderile a fost introdusă de versiunea 2.0 a limbajului, folosind metode anonime .
  • În C ++ 11 este posibil să creați o închidere prin utilizarea expresiilor lambda sau a funcției std ::.

Notă

Bibliografie

  • ( EN ) Will Clinger, Foundations of Actor Semantics ( PDF ), în AI Technical Reports , n. 633, Laboratorul de inteligență artificială MIT, 1 mai 1981.

Elemente conexe

Informatică Portal IT : accesați intrările Wikipedia care se ocupă cu IT