Domknięcie (programowanie)

W informatyce, zamknięcie jest funkcją, która posiada własne środowisko. W tym środowisku znajduje się co najmniej jedna zmienna związana (nazwa, która ma wartość, taką jak liczba). Środowisko domknięcia przechowuje związane zmienne w pamięci pomiędzy użyciami domknięcia.

Peter J. Landin nadał temu pomysłowi nazwę closure w 1964 roku. Język programowania Scheme spopularyzował domknięcia po 1975 roku. Wiele języków programowania stworzonych po tym czasie posiada domknięcia.

Funkcje anonimowe (funkcje bez nazwy) są czasami błędnie nazywane domknięciami. Większość języków, które mają funkcje anonimowe, mają również domknięcia. Funkcja anonimowa jest również domknięciem, jeśli posiada własne środowisko z co najmniej jedną zmienną związaną. Funkcja anonimowa bez własnego środowiska nie jest domknięciem. Nazwane zamknięcie nie jest anonimowe.

Domknięcia i funkcje pierwszej klasy

Wartościami mogą być liczby lub inny typ danych, np. litery, lub struktury danych składające się z prostszych części. W regułach języka programowania, wartościami pierwszej klasy są wartości, które mogą być przekazywane funkcjom, zwracane przez funkcje i wiązane z nazwą zmiennej. Funkcje, które pobierają lub zwracają inne funkcje są nazywane funkcjami wyższego rzędu. Większość języków, które mają funkcje jako wartości pierwszej klasy, ma również funkcje wyższego rzędu i domknięcia.

Na przykład, spójrz na następującą funkcję Scheme:

; Zwróć listę wszystkich książek, które sprzedały się w co najmniej TYSIĄC egzemplarzy. (define (best-selling-books threshold) (filter (lambda (book) (>= (book-sales book) threshold))      book-list))

W tym przykładzie, wyrażenie lambda (lambda (book) (>= (book-sales book) threshold)) jest częścią funkcji best-selling-books. Gdy funkcja jest uruchamiana, Scheme musi utworzyć wartość lambda. Robi to poprzez utworzenie domknięcia z kodem lambdy i referencją do zmiennej threshold, która jest zmienną wolną wewnątrz lambdy. (Zmienna wolna to nazwa, która nie jest związana z wartością).

Funkcja filtru następnie uruchamia zamknięcie na każdej książce z listy, aby wybrać książki do zwrócenia. Ponieważ samo zamknięcie posiada referencję do progu, zamknięcie może używać tej wartości za każdym razem, gdy filter uruchamia zamknięcie. Sama funkcja filter może być napisana w zupełnie osobnym pliku.

Oto ten sam przykład przepisany w ECMAScript (JavaScript), innym popularnym języku z obsługą domknięć:

// Zwróć listę wszystkich książek, które sprzedały się w co najmniej 'progowej' liczbie egzemplarzy. function bestSellingBooks(threshold) { return bookList. filter( function(book) { return book. sales >= threshold; } ); }

ECMAScript używa tutaj słowa function zamiast lambda, oraz metody Array.filter zamiast funkcji filter, ale poza tym kod robi to samo w ten sam sposób.

Funkcja może tworzyć domknięcie i zwracać je. Poniższy przykład jest funkcją, która zwraca funkcję.

W schemacie:

; Zwróć funkcję, która przybliża pochodną f ; używając przedziału dx, który powinien być odpowiednio mały. (define (pochodna f dx) (lambda (x) (/ (- (f (+ x dx))) (f x)) dx)))

W ECMAScript:

// Zwróć funkcję, która przybliża pochodną f // za pomocą przedziału dx, który powinien być odpowiednio mały. function derivative(f, dx) { return function(x) { return (f(x + dx) - f(x)) / dx; }; }

Środowisko domknięcia zachowuje związane zmienne f i dx po powrocie funkcji zamykającej (pochodnej). W językach bez domknięć, wartości te zostałyby utracone po powrocie funkcji zamykającej. W językach z domknięciami, zmienna związana musi być przechowywana w pamięci tak długo, jak długo ma ją dowolne domknięcie.

Domknięcie nie musi być utworzone przy użyciu funkcji anonimowej. Na przykład język programowania Python ma ograniczone wsparcie dla funkcji anonimowych, ale posiada domknięcia. Na przykład, jednym ze sposobów, w jaki powyższy przykład ECMAScript mógłby zostać zaimplementowany w Pythonie jest:

# Zwróć funkcję, która przybliża pochodną f # używając przedziału dx, który powinien być odpowiednio mały. def derivative(f, dx): def gradient(x): return (f(x + dx) - f(x)) / dx return gradient

W tym przykładzie funkcja o nazwie gradient tworzy zamknięcie wraz ze zmiennymi f i dx. Zewnętrzna funkcja o nazwie pochodna zwraca to zamknięcie. W tym przypadku zadziałałaby również funkcja anonimowa.

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

Python musi często używać funkcji nazwanych, ponieważ jego wyrażenia lambda mogą zawierać tylko inne wyrażenia (kod, który zwraca wartość), a nie deklaracje (kod, który ma efekty, ale nie ma wartości). Jednak w innych językach, takich jak Scheme, cały kod zwraca wartość; w Scheme wszystko jest wyrażeniem.

Zastosowania domknięć

Zamknięcia mają wiele zastosowań:

  • Projektanci bibliotek programistycznych mogą pozwolić użytkownikom na dostosowanie zachowania poprzez przekazywanie domknięć jako argumentów do ważnych funkcji. Na przykład, funkcja sortująca wartości może przyjąć argument zamknięcia, który porównuje wartości, które mają być posortowane według zdefiniowanego przez użytkownika kryterium.
  • Ponieważ domknięcia opóźniają ewaluację - tzn. nie "robią" niczego dopóki nie zostaną wywołane - mogą być używane do definiowania struktur kontrolnych. Na przykład, wszystkie standardowe struktury kontrolne Smalltalka, włączając w to rozgałęzienia (if/then/else) i pętle (while i for), są zdefiniowane przy użyciu obiektów, których metody akceptują domknięcia. Użytkownicy mogą również łatwo definiować własne struktury kontrolne.
  • Można wyprodukować wiele funkcji, które zamykają się nad tym samym środowiskiem, umożliwiając im prywatną komunikację poprzez zmianę tego środowiska (w językach, które pozwalają na przypisanie).

W programie

(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)) ; prints "none" (newline) (foo "spotkajmy się w dokach o północy") (display (bar)) ; prints "spotkajmy się w dokach o północy"
  • Zamknięcia mogą być używane do implementacji systemów obiektowych.

Uwaga: Niektórzy mówcy nazywają domknięciem dowolną strukturę danych, która wiąże środowisko leksykalne, ale termin ten zwykle odnosi się konkretnie do funkcji.

Pytania i odpowiedzi

P: Co to jest domknięcie w informatyce?


A: Domknięcie to funkcja, która ma swoje własne środowisko.

P: Co zawiera środowisko domknięcia?


A: Środowisko domknięcia zawiera co najmniej jedną zmienną związaną.

P: Kto nadał nazwę idei domknięcia?


O: Peter J. Landin nadał nazwę idei domknięcia w 1964 roku.

P: Który język programowania spopularyzował domknięcia po 1975 roku?


O: Język programowania Scheme uczynił domknięcia popularnymi po 1975 roku.

P: Czy funkcje anonimowe i domknięcia to to samo?


O: Funkcje anonimowe są czasami błędnie nazywane domknięciami, ale nie wszystkie funkcje anonimowe są domknięciami.

P: Co sprawia, że funkcja anonimowa jest domknięciem?


O: Funkcja anonimowa jest zamknięciem, jeżeli posiada własne środowisko z co najmniej jedną zmienną związaną.

P: Czy nazwane zamknięcie jest anonimowe?


O: Nie, nazwane zamknięcie nie jest anonimowe.

AlegsaOnline.com - 2020 / 2023 - License CC3