Замыкание (программирование)

Замыкание (англ. closure) в программировании — это различные методики передачи в функцию первого класса (она же callback) информации о переменных вне её тела[1]. Другими словами, это передача в функцию окольным путём некоторой информации, при каких обстоятельствах её вызвали — и наоборот, функция может окольным путём передать наружу, что случилось при её исполнении. Простейший пример: операция сортировки массива принимает функцию сравнения, а в эту функцию передаётся, по какому полю сортировать.

Замыкание, так же как и экземпляр объекта, есть способ представления функциональности и данных, связанных и упакованных вместе.

Существуют различные методики передачи в функцию замыканий:

  • Глобальная переменная, с той скидкой, что функция теряет реентерабельность — стандартная библиотека Си.
  • Дополнительный параметр, который гарантированно передаётся неизменным и позволяет упаковать небольшой объект или передать по указателю большой — низкоуровневые библиотеки наподобие WinAPI[2];
  • Объект с операцией «вызов», создаваемый каждый раз,— Си++, Java;
  • Особый вид функции — PHP.
  • Метод объекта вместе с указателем на сам объект — Delphi.

В любом случае ссылки на переменные внешней функции действительны внутри вложенной функции до тех пор, пока работает вложенная функция, даже если внешняя функция закончила работу и переменные вышли из области видимости.[3]

Замыкание связывает код функции с её лексическим окружением (местом, в котором она определена в коде). Лексические переменные замыкания отличаются от глобальных переменных тем, что они не занимают глобального пространства имён. От переменных в объектах они отличаются тем, что привязаны к функциям, а не объектам.

Некоторые из назначений

Основное назначение замыкания (в любом виде) — условно «библиотечный» код вызывает «пользовательскую» функцию (либо находящуюся на другом слое абстракции), и потому последняя обязана иметь нейтральную сигнатуру, не выдающую, какими сторонними данными происходит обмен. В частности, для механизмов «при наступлении события вызвать пользовательскую функцию»[4], «для каждого объекта вызвать пользовательскую функцию»[2], «провести сортировку в пользовательском порядке»[5]… Условно (замыкание сделано дополнительным параметром на манер WinAPI):

функция добавитьВСписок(x : целое, замык : объект)
  (замык → список).добавь(x)

y : список
пройтиПростыеЧисла(1000, добавитьВСписок, y)

Однако языковая поддержка замыканий позволила решать и другие задачи.

  1. Программирование в структурном стиле. В частности, генераторы данных и итераторы[4].
    y : список
    пройтиПростыеЧисла(1000, [y] x : целое →
      y.добавь(x)
    )
  2. Программирование в функциональном стиле — функции первого порядка, карринг, композиция функций[4].
    функция форматироватьВалюту(валюта : строка, точность : целое)
      вернуть [валюта, точность] x : дробное →
           вернуть форматировать(x, точность) + " " + валюта
    
    форматироватьЕвро = форматироватьВалюту("€", 2)
  3. Один из способов сделать скрытые (доступные только объекту-владельцу) данные, к тому же не пересекающиеся ни с одной глобальной переменной[4].
  4. Чтобы оформить небольшой объект как функцию — для кэширования предыдущих вызовов, фильтрации ввода и другого[4].

Примеры

Больше примеров смотрите в викиучебнике.

В языке Scheme

(define (make-adder n)       ; возвращает замкнутое лямбда-выражение
  (lambda (x)                ; в котором x - связанная переменная,
    (+ x n)                  ; а n - свободная (захваченная из внешнего контекста)
  )
)

(define add1 (make-adder 1)) ; делаем процедуру для прибавления 1
(add1 10)                    ; вызываем её, возвращает 11

(define sub1 (make-adder -1)); делаем процедуру для вычитания 1
(sub1 10)                    ; вызываем её, возвращает 9

В языке JavaScript[6]

'use strict';

const add = function(x) {
  return function(y) {
    const z = x + y;
    console.log(x + '+' + y + '=' + z);
    return z;
  };
};

const res = add(3)(6); // вернёт 9 и выведет в консоль 3+6=9

console.log(res);

Этот же код в версии ECMAScript2015 с использованием «стрелочных функций»:

'use strict';

const add = x => y => {
  const z = x + y;
  console.log(x + '+' + y + '=' + z);
  return z;
};

const res = add(3)(6); // вернёт 9 и выведет в консоль 3+6=9

console.log(res);

Пояснение: в JavaScript сочетание => является оператором объявления стрелочной функции, см например https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Functions/Arrow_functions. Здесь в константу add помещается функция от аргумента x, результатом которой будет являться другая функция, а именно функция от аргумента y, результат которой вычисляется приведённым в фигурных скобках блоком кода. Этот блок кода опирается на аргумент y своей функции и на замыкание, создаваемое для аргумента x внешней функции.

При вызове add(3)(6) функция, хранящаяся в переменной add, вызывается с аргументом 3 и возвращает функцию, завязанную на значение 3 в замыкании x.

Далее в рамках такого обращения эта функция выполняется с аргументом y = 6 и возвращает 9.

Можно сделать рекурсивное замыкание:

'use strict';

const add = x => y => {
  const z = x + y;
  console.log(x + '+' + y + '=' + z);
  return add(z);
};

const res = add(1)(4)(6)(9);

console.log(res);
/* 1+4=5
   5+6=11
   11+9=20
   [Function]*/

Когда JS-код работает, локальные переменные хранятся в scope. В JavaScript локальные переменные могут оставаться в памяти даже после того, как функция вернула значение.

Все функции в JavaScript — это замыкания, то есть всегда, когда создается функция, создается замыкание, хоть и зачастую оно пустое, так как функции обычно из объявления контекста, как правило, ничего не используют. Но нужно понимать разницу между созданием замыкания и созданием нового scope-объекта: замыкание (функция + ссылка на текущую цепочку scope-объектов) создается при определении функции, но новый scope-объект создается (и используется для модификации цепочки scope-объектов замыкания) при каждом вызове функции.

В языке PHP

В PHP замыкания — это анонимные функции, особые конструкции, которые позволяют описывать функции, не имеющие определённых имён.

<?php

function add($x)
{
    return function ($y) use ($x) { // <-- анонимная функция (замыкание)
        return $x + $y;
    }; // <-- эта точка с запятой здесь нужна!
}

echo add(3)(5) . PHP_EOL;   // Выведет: 8

$f = add(3);
var_dump($f);               // Выведет: object(Closure)
echo $f(6) . PHP_EOL;       // Выведет: 9

В PHP наследование переменных из родительской области видимости осуществляется с помощью конструкции use путем явного указания имен наследуемых переменных.

Другой пример с передачей замыкания в метод, где ожидается callable-параметр:

<?php

function power($arr, $exp)
{
    // переменная $func будет хранить ссылку на объект класса Closure, который описывает наше замыкание
    $func = function ($el) use ($exp) {
        return $el ** $exp;
    };
    
    return array_map($func, $arr);
}

$list = [1, 3, 4];

var_dump(power($list, 2)); // Выведет: array(3) {[0]=>int(1) [1]=>int(9) [2]=>int(16)}
var_dump(power($list, 3)); // Выведет: array(3) {[0]=>int(1) [1]=>int(27) [2]=>int(64)}

См. также

Примечания

Read other articles:

Untuk danau di Bolivia, lihat Danau Maracaibo (Bolivia). Danau MaracaiboDanau Maracaibo dari luar angkasa (STS-51-I) pada Agustus 1985. Utara ada di kiri bawah gambar.PetaKoordinat09°48′57″N 71°33′24″W / 9.81583°N 71.55667°W / 9.81583; -71.55667Koordinat: 09°48′57″N 71°33′24″W / 9.81583°N 71.55667°W / 9.81583; -71.55667Jenis perairanAir asin pesisir, telurAliran masuk utamaSungai CatatumboAliran keluar utamaTeluk Venezuel...

 

Akademi Komunitas Negeri Putra Sang Fajar BlitarMotoSmart, Adaptive, ExcellentJenisAkademi komunitasDidirikan2014Lembaga indukKementerian Pendidikan, Kebudayaan, Riset, dan Teknologi Republik IndonesiaRektorDr. Drs. Halid Hasan, M. Strat., H.R.MAlamatJalan dr. Sutomo 29, Blitar, Jawa Timur, IndonesiaSitus webakb.ac.id Akademi Komunitas Negeri Putra Sang Fajar Blitar atau AKB adalah perguruan tinggi negeri berbentuk akademi komunitas yang berada di Kota Blitar dan dikelola oleh Kementerian Pen...

 

هذه المقالة بحاجة لصندوق معلومات. فضلًا ساعد في تحسين هذه المقالة بإضافة صندوق معلومات مخصص إليها. يُعتقد أن الاشتراكية في المملكة المتحدة تمتد إلى القرن التاسع عشر، من الجذور التي نشأت في أعقاب الحرب الأهلية الإنجليزية. اتخذت مفاهيم الاشتراكية في بريطانيا العظمى العديد �...

French footballer Grégory Thil Thil with Châteauroux in 2014Personal informationDate of birth (1980-03-15) 15 March 1980 (age 44)Place of birth Creil, FranceHeight 1.83 m (6 ft 0 in)Position(s) ForwardYouth career1986–1998 US Balagny1998–2001 US MouySenior career*Years Team Apps (Gls)2001–2005 Beauvais 98 (26)2005–2011 Boulogne 204 (94)2011–2015 Dijon 47 (5)2014–2015 → Châteauroux (loan) 37 (6)2015–2018 Boulogne 95 (25)2018–2019 Jura Sud 28 (12)2019–...

 

Artikel ini tidak memiliki referensi atau sumber tepercaya sehingga isinya tidak bisa dipastikan. Tolong bantu perbaiki artikel ini dengan menambahkan referensi yang layak. Tulisan tanpa sumber dapat dipertanyakan dan dihapus sewaktu-waktu.Cari sumber: Hari Perjuangan Tani Internasional – berita · surat kabar · buku · cendekiawan · JSTOR Hari Perjuangan Tani Internasional, yang diperingati setiap tanggal 17 April, merupakan momen penting untuk mengenan...

 

Sir Hector Maclean, 7th Baronet, 3rd Lord Maclean and 23rd Clan Chief23rd Clan Chief7th Baronet3rd Lord MacleanIn office1783-1818Preceded bySir Allan Maclean, 6th Baronet, cousinSucceeded bySir Fitzroy Jeffreys Grafton Maclean, 8th Baronet, half brother Personal detailsBornHector Macleanabout 1760Died2 November 1818(1818-11-02) (aged 58)Halfield, YorkshireParentDonald Maclean of BrolasRelativesSir Fitzroy Jeffreys Grafton Maclean, 8th Baronet, half brotherDonald MacLean, 1st Laird of Br...

Robert A. Armstrong, owner of the Buccaneer Hotel in 1998. The Buccaneer, formally known as The Buccaneer Beach & Golf Resort, is a luxury historic hotel and beach resort about 3 miles (4.8 km) northeast of Christiansted, on the island of Saint Croix, U. S. Virgin Islands, beyond Altona Lagoon.[1] Set in 240 acres with an 18-hole golf course and three private beaches, it was opened by the Armstrong family as an inn in 1947 and was listed on the National Registry of the Histor...

 

The Winthrop BallparkLocation290 University Lake Drive, Rock Hill, South Carolina, U.S.Coordinates34°56′45″N 81°01′07″W / 34.945794°N 81.018575°W / 34.945794; -81.018575OwnerWinthrop UniversityOperatorWinthrop UniversityExecutive suites1Capacity1,989SurfaceNatural grassScoreboardElectronicConstructionRenovated2000–01, 2008Construction cost$2.2 million (2000–01 renovations)TenantsWinthrop Eagles (NCAA) The Winthrop Ballpark is a baseball venue in Rock Hi...

 

Extinct genus of armored fish AmazichthysTemporal range: Famennian PreꞒ Ꞓ O S D C P T J K Pg N Holotype specimen AA.MEM.DS.8 (A and B), and paratype PIMUZ A/I 4773 (C, D) Life reconstruction Scientific classification Domain: Eukaryota Kingdom: Animalia Phylum: Chordata Class: †Placodermi Order: †Arthrodira Suborder: †Brachythoraci Family: †Selenosteidae Genus: †AmazichthysJobbins et al, 2022 Species: †A. trinajsticae Binomial name †Amazichthys trinajsticaeJobbin...

Andy Myers Informasi pribadiNama lengkap Andrew John Myers[1]Tanggal lahir 3 November 1973 (umur 50)Tempat lahir Hounslow, EnglandTinggi 5 ft 10 in (1,78 m)Posisi bermain DefenderInformasi klubKlub saat ini Chelsea U18(manager)Karier junior0000–1991 ChelseaKarier senior*Tahun Tim Tampil (Gol)1991–1999 Chelsea 85 (2)1999–2003 Bradford City 89 (3)2000 → Portsmouth (loan) 8 (0)2003–2004 Colchester United 21 (0)2004–2005 Brentford 10 (0)Total 213 (5)Tim na...

 

This article does not cite any sources. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed.Find sources: Moldavian-Muntenian Carpathians – news · newspapers · books · scholar · JSTOR (August 2021) (Learn how and when to remove this message) Moldavian-Muntenian Carpathians, marked in red and labeled with D See also: Romanian Carpathians The Moldavian-Muntenian Carpathians are a grou...

 

Robert Schuman en 1949. La Declaración Schuman es el título con el que se conoce el discurso pronunciado por Robert Schuman, ministro de Asuntos Exteriores francés, el 9 de mayo de 1950. En la declaración se propone que una Europa unida puede contribuir a la paz mundial, a través de realizaciones concretas.[1]​ La Comisión Europea reconoce esta declaración como el nacimiento de la Unión Europea (UE),[2]​ al proponer que el carbón y el acero de Alemania (es decir, de la Re...

1998 Japanese horror film by Hideo Nakata This article is about the 1998 Japanese horror film. For other uses, see Ring (disambiguation). RingJapanese theatrical release posterJapanese nameKatakanaリングTranscriptionsRevised HepburnRingu Directed byHideo NakataScreenplay byHiroshi Takahashi[1]Based onRingby Koji SuzukiProduced by Shinya Kawai Taka Ichise Takenori Sento[2] Starring Nanako Matsushima Hiroyuki Sanada Rikiya Otaka Miki Nakatani Yuko Takeuchi Hitomi Sato Yutaka ...

 

Peta infrastruktur dan tata guna lahan di Komune Rempnat.  = Kawasan perkotaan  = Lahan subur  = Padang rumput  = Lahan pertanaman campuran  = Hutan  = Vegetasi perdu  = Lahan basah  = Anak sungaiRempnat merupakan sebuah komune di departemen Haute-Vienne di Prancis. Lihat pula Komune di departemen Haute-Vienne Referensi INSEE lbsKomune di departemen Haute-Vienne Aixe-sur-Vienne Ambazac Arnac-la-Poste Augne Aureil Azat-le-Ris Balledent La Bazeuge Beaumon...

 

Hermandad del Santo Cristo de los ArtillerosLocalizaciónPaís  EspañaLocalidad ValladolidSede canónica Iglesia Conventual de Santa Isabel de HungríaDatos generalesFundación 1944Pasos DosTúnica      Capirote, cíngulo y bocamangas rojos     Túnica morada     Guantes blancos     Zapatos negrosProcesionesDía y hora Procesión de la Hermandad del Santo Cristo de los Artilleros (S�...

يفتقر محتوى هذه المقالة إلى الاستشهاد بمصادر. فضلاً، ساهم في تطوير هذه المقالة من خلال إضافة مصادر موثوق بها. أي معلومات غير موثقة يمكن التشكيك بها وإزالتها. (ديسمبر 2018) أستراليا كأس العالم 2006 الاتحاد المشرف اتحاد أستراليا لكرة القدم البلد المضيف  ألمانيا المدرب غوس هيدي...

 

  لمعانٍ أخرى، طالع الهدية (توضيح). الهدية تقسيم إداري  البلد السعودية  التقسيم الأعلى مدينة بريدة  تعديل مصدري - تعديل   الهدية هو مركزٌ سعوديٌ تابعٌ لمحافظة بريدة التابعة لمنطقة القصيم، في المملكة العربية السعودية. المركز من الفئة (ب)، ورمزه 1747 حسب الدليل ال�...

 

Family of flowering plants Philesiaceae Lapageria rosea Scientific classification Kingdom: Plantae Clade: Tracheophytes Clade: Angiosperms Clade: Monocots Order: Liliales Family: PhilesiaceaeDumort.[1] Genera See text   Philesiaceae distribution Philesiaceae is a family of flowering plants, including two genera, each with a single species.[2] The members of the family are woody shrubs or vines endemic to southern Chile.[3][4] The APG III system, of 20...

1991 action film This stub needs additional citations for verification. Please help improve this article by adding citations to reliable sources in this stub. Unsourced material may be challenged and removed.Find sources: Martial Law 1991 film – news · newspapers · books · scholar · JSTOR (October 2023) (Learn how and when to remove this message) Martial LawDirected bySteve CohenWritten byRichard BrandesProduced byKurt AndersonStarringChad McQ...

 

Hotel at Walt Disney World This article needs additional citations for verification. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed.Find sources: Disney's Yacht Club Resort – news · newspapers · books · scholar · JSTOR (November 2019) (Learn how and when to remove this message) Disney's Yacht Club ResortSunrise over Disney's Yacht Club ResortLocationEpcot Resort AreaResort typ...