Slēgums (datorzinātne): definīcija, piemēri un pielietojums

Uzzini, kas ir slēgums datorzinātnē — definīcija, praktiski piemēri un pielietojums programmēšanā. Saprotami kodu paraugi un skaidrojumi.

Autors: Leandro Alegsa

Datorzinātnē slēgums ir funkcija, kurai ir sava vide. Šajā vidē ir vismaz viens piesaistīts mainīgais (vārds, kam ir vērtība, piemēram, skaitlis). Slēguma vide saglabā piesaistītos mainīgos atmiņā starp slēguma lietošanas reizēm.

Pīters J. Landins 1964. gadā šai idejai deva nosaukumu "slēgšana". Scheme programmēšanas valoda pēc 1975. gada padarīja slēgšanu populāru. Daudzās programmēšanas valodās, kas radītas pēc šī laika, ir slēgumi.

Anonīmās funkcijas (funkcijas bez nosaukuma) dažkārt kļūdaini sauc par slēgumiem. Lielākajā daļā valodu, kurās ir anonīmās funkcijas, ir arī slēgšanas funkcijas. Arī anonīma funkcija ir slēgums, ja tai ir sava vide ar vismaz vienu piesaistītu mainīgo. Anonīma funkcija, kurai nav savas vides, nav slēgums. Nosaukta slēgšana nav anonīma.

Vienkārša definīcija un būtība

Vienkārši sakot, slēgums ir funkcija kopā ar to saistīto vidi. Kad funkcija tiek izveidota, tā „aiznes līdzi” atsauces uz mainīgajiem, kuri bija pieejami tās izveides laikā. Pat ja šī vide vairs nav pieejama lokālā izpildes kontekstā, slēgums saglabā piekļuvi šiem mainīgajiem, līdz slēgums vairs netiek izmantots un atkritumu savācējs tos iztīra.

Kā slēgums darbojas — piemēri

Zemāk ir vienkāršs piemērs JavaScript valodā, kas ilustrē skaitītāja slēgumu:

function makeCounter() {   let count = 0;   return function() {     count += 1;     return count;   }; }  const counter = makeCounter(); console.log(counter()); // 1 console.log(counter()); // 2 

Šeit iekšējā funkcija ir slēgums: tā saglabā piekļuvi mainīgajam count, pat pēc tam, kad makeCounter izpilde ir beigusies.

Analogs piemērs Python (lambda vai iekšējā funkcija):

def make_counter():     count = 0     def inc():         nonlocal count         count += 1         return count     return inc  c = make_counter() print(c())  # 1 print(c())  # 2 

Leģiskā (lexical) vs dinamiskā skopēšana

Lielākā daļa mūsdienu valodu ar slēgumiem izmanto leksisko skopēšanu — mainīgo atsauces asociējas ar vietām koda struktūras laikā (kur funkcija tika definēta), nevis ar to, kur funkcija tiek izsaukta. Tas ļauj slēgumiem pārliecinoši „aiznest” kontekstu no definīcijas vietas. Dažas valodas vai izpildes vidi var izmantot dinamisku scoping, bet tas ir retāk sastopams un rada citāda veida uzvedību.

Implementācijas atslēgas

  • Slēgums satur atsauci uz funkcionālo kodu un uz vidē esošajām saistībām (bindings).
  • Atmiņas pārvaldība (garbage collection) parasti nodrošina, ka vide netiek atbrīvota, kamēr pastāv atsauce uz to no slēguma.
  • Dažas valodas saglabā pilnu vides kopiju, citas — tikai atsauces uz nepieciešamajiem mainīgajiem; realizācija ietekmē veiktspēju un atmiņas patēriņu.

Pielietojumi

Slēgumi ir ļoti praktiski un tiek izmantoti daudzos kontekstos:

  • Inkapsulācija un privātie dati: ļauj izveidot funkcijas vai objektus ar privātām mainīgajām, pieejamām tikai caur publiskajām metodēm.
  • Fabrikas funkcijas: ģenerēt specializētas funkcijas ar iepriekš noteiktu konfigurāciju.
  • Kallbacki un notikumu apstrāde: saglabāt stāvokli starp asinhroniem izsaukumiem.
  • Daļēja piemērošana un karings: atgriezt jaunas funkcijas ar jau fiksētām dažām argumentu vērtībām.
  • Iteratori un generatori: uzturēt iekšējo stāvokli starp seansiem.

Bieži sastopamas kļūdas un uzmanības punkti

  • Neintuitīvas atsauces cilpās: valodās, kurās lokālie mainīgie cilpā tiek koplietoti (piemēram, JS ar var), visas anonīmās funkcijas var saistīt vienu un to pašu mainīgo. Izmantojot let vai izveidojot atsevišķu slēgumu katrai iterācijai, šo problēmu var novērst.
  • Atmiņas noplūdes risks: ja slēgumi tur ilgi dzīvojošas atsauces uz lieliem datiem, var rasties nevēlama atmiņas izmantošana.
  • Reassignācija: dažās valodās, lai mainītu ārējo mainīgo no iekšējās funkcijas, nepieciešams speciāls atslēgas vārds (piem., Python — nonlocal, global).

Papildus piezīmes

Terminoloģija var dažkārt sajaukties: ne visas anonīmās funkcijas ir slēgumi — tās kļūst par slēgumiem tikai tad, ja tām ir piesaistīta vide. Tāpat, slēgums nav tikai funkcionāla programmēšanas īpašība — tas ir plaši izmantots paradigmu savienojums, kas ir pieejams daudzās imperatīvajās, objektorientētajās un funkcionālajās valodās.

Šī koncepcija ir fundamentāla mūsdienu programmēšanai: sapratne par to, kā slēgumi uztur stāvokli un kā tie ietekmē skopēšanu un dzīves ilgumu, palīdz rakstīt drošāku, modulārāku un vieglāk uzturamu kodu.

Slēgšana un pirmās klases funkcijas

Vērtības var būt skaitļi vai cita veida dati, piemēram, burti, vai datu struktūras, kas sastāv no vienkāršākām daļām. Programmēšanas valodas noteikumos pirmās klases vērtības ir vērtības, kuras var piešķirt funkcijām, kuras funkcijas var atdot un kuras var saistīt ar mainīgā vārdu. Funkcijas, kas pieņem vai atdod citas funkcijas, sauc par augstākās kārtas funkcijām. Lielākajā daļā valodu, kurās funkcijas ir pirmās klases vērtības, ir arī augstākas kārtas funkcijas un slēgumi.

Piemēram, aplūkojiet šādu Scheme funkciju:

; Atgrieziet sarakstu ar visām grāmatām, kuru pārdoto eksemplāru skaits ir vismaz TISĪKS. (define (best-selling-books threshold) (filter (lambda (book) (>= (book-sales book) threshold))) book-list))))

Šajā piemērā lambda izteiksme (lambda (grāmata) (>= (grāmata-pārdod grāmatu) slieksnis)) ir daļa no funkcijas best-selling-books. Kad funkcija tiek palaista, Scheme ir jāveido lambda vērtība. Tas tiek darīts, izveidojot slēgumu ar lambda kodu un atsauci uz mainīgo threshold, kas ir brīvs mainīgais lambda iekšienē. (Brīvs mainīgais ir vārds, kas nav piesaistīts vērtībai.)

Filtrēšanas funkcija pēc tam veic katras sarakstā esošās grāmatas slēgšanu, lai izvēlētos, kuras grāmatas atgriezt. Tā kā pašam slēgumam ir atsauce uz slieksni, slēgums var izmantot šo vērtību katru reizi, kad filtrs izpilda slēgumu. Pašu funkciju filtrs var ierakstīt pilnīgi atsevišķā failā.

Šeit ir tas pats piemērs, kas pārrakstīts ECMAScript (JavaScript) - vēl vienā populārā valodā ar slēgšanas atbalstu:

// Atgriež sarakstu ar visām grāmatām, kuru pārdoto eksemplāru skaits ir vismaz 'slieksnis'. function bestSellingBooks(threshold) { return bookList. filter( function(book) { return book. sales >= threshold; }     ); }

ECMAScript šeit lambda vietā tiek lietots vārds funkcija, bet filtru funkcijas vietā - metode Array.filter, taču citādi kods veic to pašu darbību tādā pašā veidā.

Funkcija var izveidot un atgriezt slēgtni. Nākamajā piemērā ir funkcija, kas atgriež funkciju.

Shēmā:

; Atgrieziet funkciju, kas aproksimē f atvasinājumu ; izmantojot dx intervālu, kuram jābūt attiecīgi mazam. (define (derivative f dx) (lambda (x) (/ (- (f (+ x dx))) (f x)) dx))))))

In ECMAScript:

// Atgrieziet funkciju, kas aproksimē f atvasinājumu // izmantojot dx intervālu, kuram jābūt attiecīgi mazam. funkcija derivative(f, dx) { return function(x) { return (f(x + dx) - f(x))) / dx; }; }; }

Noslēguma vide saglabā saistītos mainīgos f un dx pēc tam, kad ir atgriezta ietverošā funkcija (atvasinājums). Valodās bez slēgšanas funkcijām šīs vērtības tiktu pazaudētas pēc tam, kad ieslēdzošā funkcija atgriežas. Valodās ar slēgtām funkcijām piesaistītais mainīgais ir jāsaglabā atmiņā, kamēr vien tas ir kādā no slēgtajām funkcijām.

Slēgums nav jāveido, izmantojot anonīmu funkciju. Piemēram, Python programmēšanas valodai ir ierobežots atbalsts anonīmām funkcijām, bet tajā ir slēgšanas funkcijas. Piemēram, viens no veidiem, kā iepriekš minēto ECMAScript piemēru varētu īstenot Python valodā, ir šāds:

# Atgrieziet funkciju, kas aproksimē f atvasinājumu, izmantojot dx intervālu, kuram jābūt attiecīgi mazam. def derivative(f, dx): def gradient(x): return (f(x + dx) - f(x)) / dx return gradient

Šajā piemērā funkcija ar nosaukumu gradients veido slēgumu kopā ar mainīgajiem f un dx. Ārējā norobežojošā funkcija ar nosaukumu derivative atdod šo slēgumu. Šajā gadījumā darbotos arī anonīma funkcija.

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

Python tā vietā bieži ir jāizmanto nosauktās funkcijas, jo tā lambda izteiksmes var saturēt tikai citas izteiksmes (kodu, kas atgriež vērtību), nevis paziņojumus (kodu, kam ir sekas, bet nav vērtības). Taču citās valodās, piemēram, Scheme, visi kodi atgriež vērtību; Scheme viss ir izteiksme.

Noslēgumu lietojums

Aizvērumiem ir daudz pielietojumu:

  • Programmatūras bibliotēku izstrādātāji var ļaut lietotājiem pielāgot uzvedību, nododot slēgumus kā argumentus svarīgām funkcijām. Piemēram, funkcija, kas šķiro vērtības, var pieņemt slēgšanas argumentu, kas salīdzina šķirojamās vērtības atbilstoši lietotāja noteiktam kritērijam.
  • Tā kā aizvērumi aizkavē izvērtēšanu, t. i., tie neko "nedara", kamēr tie netiek izsaukti, tos var izmantot, lai definētu vadības struktūras. Piemēram, visas Smalltalk standarta vadības struktūras, ieskaitot atzarus (if/then/else) un cilpas (while un for), ir definētas, izmantojot objektus, kuru metodes pieņem slēgumus. Lietotāji var viegli definēt arī savas kontroles struktūras.
  • Var izveidot vairākas funkcijas, kas ir saistītas ar vienu un to pašu vidi, ļaujot tām privāti sazināties, mainot šo vidi (valodās, kas ļauj veikt uzdevumus).

Shēmā

(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)) ; drukā "none" (newline) (foo "meet me by the docks at midnight") (display (bar)) ; drukā "meet me by the docks at midnight"
  • Objektu sistēmu ieviešanai var izmantot slēgumus.

Piezīme: Daži runātāji par slēgumu sauc jebkuru datu struktūru, kas saista leksisko vidi, taču parasti šis termins attiecas tieši uz funkcijām.

Jautājumi un atbildes

J: Kas ir slēgšana datorzinātnē?


A: Slēgums ir funkcija, kurai ir sava vide.

J: Ko satur slēguma vide?


A: Slēguma vidē ir vismaz viens piesaistītais mainīgais.

J: Kurš deva slēguma ideju?


A: Pīters J. Landins 1964. gadā deva slēguma ideju.

J: Kura programmēšanas valoda pēc 1975. gada popularizēja slēgumus?


A: Scheme programmēšanas valoda pēc 1975. gada popularizēja slēgumus.

J: Vai anonīmās funkcijas un slēgumi ir viens un tas pats?


A: Anonīmās funkcijas dažkārt kļūdaini sauc par slēgumiem, bet ne visas anonīmās funkcijas ir slēgumi.

J: Kas padara anonīmu funkciju par slēgumu?


A: Anonīma funkcija ir slēgtā funkcija, ja tai ir sava vide ar vismaz vienu piesaistītu mainīgo.

J: Vai nosaukta slēgšana ir anonīma?


A: Nē, nosaukta slēgšana nav anonīma.


Meklēt
AlegsaOnline.com - 2020 / 2025 - License CC3