Затваряне (информатика)

В информатиката затварянето е функция, която има собствена среда. В тази среда има поне една обвързана променлива (име, което има стойност, например число). Средата на затварянето съхранява обвързаните променливи в паметта между употребите на затварянето.

През 1964 г. Питър Джей Ландин дава на тази идея името "затваряне". След 1975 г. езикът за програмиране Scheme прави затварянето популярно. Много езици за програмиране, създадени след това, имат затваряния.

Анонимните функции (функции без име) понякога неправилно се наричат затваряния. Повечето езици, които имат анонимни функции, имат и затваряния. Една анонимна функция също е затваряне, ако има собствена среда с поне една обвързана променлива. Анонимна функция, която няма собствена среда, не е затваряне. Именувана затваряща функция не е анонимна.

Затваряне и първокласни функции

Стойностите могат да бъдат числа или друг вид данни, например букви, или структури от данни, съставени от по-прости части. В правилата на един език за програмиране стойностите от първи клас са стойности, които могат да се дават на функции, да се връщат от функции и да се свързват с име на променлива. Функциите, които приемат или връщат други функции, се наричат функции от по-висок клас. Повечето езици, в които функциите са стойности от първи клас, имат и функции от по-висок ред и затваряния.

Вижте например следната функция на схемата:

; Връщане на списък с всички книги с поне ТРИ хиляди продадени копия. (define (best-selling-books threshold) (filter (lambda (book) (>= (book-sales book) threshold)) book-list))

В този пример ламбда изразът (ламбда (book) (>= (book-sales book) threshold)) е част от функцията best-selling-books. Когато функцията се изпълнява, Scheme трябва да направи стойността на ламбда израза. Тя прави това, като създава затваряне с кода на ламбдата и препратка към променливата threshold, която е свободна променлива вътре в ламбдата. (Свободна променлива е име, което не е обвързано със стойност.)

След това функцията за филтриране изпълнява затварянето на всяка книга в списъка, за да избере кои книги да върне. Тъй като самото затваряне има препратка към прага, затварянето може да използва тази стойност всеки път, когато филтърът изпълнява затварянето. Самата функция филтър може да бъде записана в напълно отделен файл.

Ето същия пример, пренаписан на ECMAScript (JavaScript) - друг популярен език с поддръжка на затваряния:

// Връщане на списък с всички книги с продадени поне 'праг' копия. function bestSellingBooks(threshold) { return bookList. filter( function(book) { return book. sales >= threshold; }     ); }

ECMAScript използва думата function вместо lambda и метода Array.filter вместо функцията filter, но иначе кодът прави същото нещо по същия начин.

Функцията може да създаде затваряне и да го върне. Следващият пример е функция, която връща функция.

В схемата:

; Връщане на функция, която приближава производната на f ; използвайки интервал от dx, който трябва да е подходящо малък. (define (derivative f dx) (lambda (x) (/ (- (f (+ x dx)) (f x)) dx)))

В ECMAScript:

// Връщане на функция, която апроксимира производната на f // с помощта на интервал от dx, който трябва да е подходящо малък. функция derivative(f, dx) { return function(x) { return (f(x + dx) - f(x)) / dx; }; }

Средата на затваряне запазва обвързаните променливи f и dx след връщането на ограждащата функция (производна). В езици без затваряне тези стойности биха били изгубени след връщането на ограждащата функция. В езиците със затваряния обвързаната променлива трябва да се пази в паметта, докато някое затваряне я има.

Не е задължително затварянето да се формира с помощта на анонимна функция. Езикът за програмиране Python например има ограничена поддръжка на анонимни функции, но има затваряния. Например един от начините, по които горният пример на ECMAScript може да бъде реализиран на езика Python, е:

# Върнете функция, която апроксимира производната на f # с помощта на интервал от dx, който трябва да е подходящо малък. def derivative(f, dx): def gradient(x): return (f(x + dx) - f(x)) / dx return gradient

В този пример функцията, наречена gradient, се затваря заедно с променливите f и dx. Външната ограждаща функция, наречена дериватив, връща това затваряне. В този случай би работила и анонимна функция.

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

Вместо това Python често трябва да използва именувани функции, тъй като неговите ламбда изрази могат да съдържат само други изрази (код, който връща стойност), но не и оператори (код, който има ефекти, но няма стойност). Но в други езици, като Scheme, всички кодове връщат стойност; в Scheme всичко е израз.

Употреби на затворите

Затворите имат много приложения:

  • Дизайнерите на софтуерни библиотеки могат да позволят на потребителите да персонализират поведението си, като предават затваряния като аргументи на важни функции. Например функция, която подрежда стойности, може да приеме аргумент за затваряне, който сравнява стойностите, които трябва да бъдат подредени, според определен от потребителя критерий.
  • Тъй като затварянето забавя оценката, т.е. не "прави" нищо, докато не бъде извикано, то може да се използва за дефиниране на структури за управление. Например всички стандартни структури за управление на Smalltalk, включително разклонения (if/then/else) и цикли (while и for), са дефинирани с помощта на обекти, чиито методи приемат затваряния. Потребителите могат лесно да дефинират и свои собствени структури за управление.
  • Могат да бъдат създадени няколко функции, които се затварят в една и съща среда, което им позволява да общуват частно, като променят тази среда (на езици, които позволяват присвояване).

В схемата

(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 "meet me by the docks at midnight") (display (bar)) ; prints "meet me by the docks at midnight"
  • Затварянията могат да се използват за реализиране на обектни системи.

Забележка: Някои автори наричат всяка структура от данни, която свързва лексикална среда, затваряне, но този термин обикновено се отнася конкретно за функции.

Въпроси и отговори

В: Какво представлява закриването на компютърни науки?


О: Затварянето е функция, която има собствена среда.

Въпрос: Какво съдържа средата на един завършек?


О.: Средата на затваряне съдържа поне една обвързана променлива.

Въпрос: Кой е дал името на идеята за затваряне?


О: Питър Й. Ландин дава името на идеята за затваряне през 1964 г.

Въпрос: Кой език за програмиране направи затворите популярни след 1975 г.?


О: Езикът за програмиране Scheme направи затворите популярни след 1975 г.

Въпрос: Анонимните функции и затварянията едно и също нещо ли са?


О: Анонимните функции понякога погрешно се наричат затваряния, но не всички анонимни функции са затваряния.

В: Какво прави една анонимна функция затваряне?


О: Една анонимна функция е затваряне, ако има собствена среда с поне една обвързана променлива.

Въпрос: Анонимна ли е именувана затваряща функция?


О: Не, именуваният завършек не е анонимен.

AlegsaOnline.com - 2020 / 2023 - License CC3