[{"@context":"http:\/\/schema.org\/","@type":"BlogPosting","@id":"https:\/\/wiki.edu.vn\/wiki15\/2020\/12\/24\/schliesung-computerprogrammierung-wikipedia\/#BlogPosting","mainEntityOfPage":"https:\/\/wiki.edu.vn\/wiki15\/2020\/12\/24\/schliesung-computerprogrammierung-wikipedia\/","headline":"Schlie\u00dfung (Computerprogrammierung) – Wikipedia","name":"Schlie\u00dfung (Computerprogrammierung) – Wikipedia","description":"Nicht zu verwechseln mit der Programmiersprache Clojure. In Programmiersprachen a Schlie\u00dfung, ebenfalls lexikalischer Verschluss oder Funktionsschlussist eine Technik zum Implementieren","datePublished":"2020-12-24","dateModified":"2020-12-24","author":{"@type":"Person","@id":"https:\/\/wiki.edu.vn\/wiki15\/author\/lordneo\/#Person","name":"lordneo","url":"https:\/\/wiki.edu.vn\/wiki15\/author\/lordneo\/","image":{"@type":"ImageObject","@id":"https:\/\/secure.gravatar.com\/avatar\/44a4cee54c4c053e967fe3e7d054edd4?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/44a4cee54c4c053e967fe3e7d054edd4?s=96&d=mm&r=g","height":96,"width":96}},"publisher":{"@type":"Organization","name":"Enzyklop\u00e4die","logo":{"@type":"ImageObject","@id":"https:\/\/wiki.edu.vn\/wiki4\/wp-content\/uploads\/2023\/08\/download.jpg","url":"https:\/\/wiki.edu.vn\/wiki4\/wp-content\/uploads\/2023\/08\/download.jpg","width":600,"height":60}},"image":{"@type":"ImageObject","@id":"https:\/\/wiki.edu.vn\/wiki4\/wp-content\/uploads\/2023\/08\/download.jpg","url":"https:\/\/wiki.edu.vn\/wiki4\/wp-content\/uploads\/2023\/08\/download.jpg","width":100,"height":100},"url":"https:\/\/wiki.edu.vn\/wiki15\/2020\/12\/24\/schliesung-computerprogrammierung-wikipedia\/","wordCount":15301,"articleBody":"Nicht zu verwechseln mit der Programmiersprache Clojure.In Programmiersprachen a Schlie\u00dfung, ebenfalls lexikalischer Verschluss oder Funktionsschlussist eine Technik zum Implementieren der lexikalischen Namensbindung in einer Sprache mit erstklassigen Funktionen. Operativ ist ein Abschluss ein Datensatz, in dem eine Funktion gespeichert ist[a] zusammen mit einer Umgebung.[1] Die Umgebung ist eine Zuordnung, die jede freie Variable der Funktion (Variablen, die lokal verwendet, aber in einem umschlie\u00dfenden Bereich definiert werden) mit dem Wert oder der Referenz verkn\u00fcpft, an die der Name beim Erstellen des Abschlusses gebunden wurde.[b] Im Gegensatz zu einer einfachen Funktion erm\u00f6glicht ein Verschluss der Funktion den Zugriff auf diese erfasste Variablen durch die Kopien ihrer Werte oder Referenzen des Abschlusses, selbst wenn die Funktion au\u00dferhalb ihres G\u00fcltigkeitsbereichs aufgerufen wird. Table of ContentsGeschichte und Etymologie[edit]Anonyme Funktionen[edit]Anwendungen[edit]Erstklassige Funktionen[edit]Staatsvertretung[edit]Andere Verwendungen[edit]Implementierung und Theorie[edit]Unterschiede in der Semantik[edit]Lexikalische Umgebung[edit]Beispiel 1: Verweis auf eine ungebundene Variable[edit]Beispiel 2: Versehentlicher Verweis auf eine gebundene Variable[edit]Schlie\u00dfung verlassen[edit]Verschlussartige Konstrukte[edit]R\u00fcckrufe (C)[edit]Verschachtelte Funktion und Funktionszeiger (C)[edit]Lokale Klassen und Lambda-Funktionen (Java)[edit]Bl\u00f6cke (C, C ++, Objective-C 2.0)[edit]Delegierte (C #, VB.NET, D)[edit]Funktionsobjekte (C ++)[edit]Inline-Agenten (Eiffel)[edit]C ++ Builder __closure reserviertes Wort[edit]Siehe auch[edit]Verweise[edit]Externe Links[edit]Geschichte und Etymologie[edit]Das Konzept der Verschl\u00fcsse wurde in den 1960er Jahren f\u00fcr die mechanische Bewertung von Ausdr\u00fccken im \u03bb-Kalk\u00fcl entwickelt und 1970 erstmals vollst\u00e4ndig als Sprachmerkmal in der Programmiersprache PAL implementiert, um lexikalisch ausgerichtete erstklassige Funktionen zu unterst\u00fctzen.[2]Peter J. Landin definierte den Begriff Schlie\u00dfung im Jahr 1964 als mit einem Umwelt Teil und ein Steuerteil wie von seiner SECD-Maschine zur Auswertung von Ausdr\u00fccken verwendet.[3]Joel Moses schreibt Landin die Einf\u00fchrung des Begriffs zu Schlie\u00dfung sich auf einen Lambda-Ausdruck zu beziehen, dessen offene Bindungen (freie Variablen) durch die lexikalische Umgebung geschlossen (oder in diese gebunden) wurden, was zu a f\u00fchrt geschlossener Ausdruckoder Schlie\u00dfung.[4][5] Diese Verwendung wurde sp\u00e4ter von Sussman und Steele \u00fcbernommen, als sie 1975 das Schema definierten.[6] eine lexikalisch begrenzte Variante von LISP und verbreitete sich. Anonyme Funktionen[edit]Der Begriff Schlie\u00dfung wird oft als Synonym f\u00fcr anonyme Funktion verwendet, obwohl eine anonyme Funktion streng genommen ein Funktionsliteral ohne Namen ist, w\u00e4hrend ein Abschluss eine Instanz einer Funktion ist, ein Wert, dessen nicht-lokale Variablen entweder an Werte oder an gebunden sind Speicherorte (abh\u00e4ngig von der Sprache; siehe Abschnitt \u00fcber die lexikalische Umgebung unten).Zum Beispiel im folgenden Python-Code:def f(x): def g(y): return x + y return g # Return a closure.def h(x): return lambda y: x + y # Return a closure.# Assigning specific closures to variables.a = f(1)b = h(1)# Using the closures stored in variables.assert a(5) == 6assert b(5) == 6# Using closures without binding them to variables first.assert f(1)(5) == 6 # f(1) is the closure.assert h(1)(5) == 6 # h(1) is the closure.die Werte von a und b sind Abschl\u00fcsse, die in beiden F\u00e4llen durch R\u00fcckgabe einer verschachtelten Funktion mit einer freien Variablen aus der umschlie\u00dfenden Funktion erzeugt werden, so dass die freie Variable an den Wert des Parameters bindet x der umschlie\u00dfenden Funktion. Die Verschl\u00fcsse in a und b sind funktional identisch. Der einzige Unterschied bei der Implementierung besteht darin, dass wir im ersten Fall eine verschachtelte Funktion mit einem Namen verwendet haben. gIm zweiten Fall haben wir eine anonyme verschachtelte Funktion verwendet (mit dem Schl\u00fcsselwort Python lambda zum Erstellen einer anonymen Funktion). Der urspr\u00fcngliche Name, falls vorhanden, um sie zu definieren, ist irrelevant.Ein Abschluss ist ein Wert wie jeder andere Wert. Es muss keiner Variablen zugewiesen werden und kann stattdessen direkt verwendet werden, wie in den letzten beiden Zeilen des Beispiels gezeigt. Diese Nutzung kann als “anonyme Schlie\u00dfung” angesehen werden. Die verschachtelten Funktionsdefinitionen sind selbst keine Abschl\u00fcsse: Sie haben eine freie Variable, die noch nicht gebunden ist. Erst wenn die einschlie\u00dfende Funktion mit einem Wert f\u00fcr den Parameter ausgewertet wird, wird die freie Variable der verschachtelten Funktion gebunden, wodurch ein Abschluss erstellt wird, der dann von der einschlie\u00dfenden Funktion zur\u00fcckgegeben wird.Schlie\u00dflich unterscheidet sich ein Abschluss nur dann von einer Funktion mit freien Variablen, wenn er au\u00dferhalb des Bereichs der nicht lokalen Variablen liegt. Andernfalls stimmen die definierende Umgebung und die Ausf\u00fchrungsumgebung \u00fcberein, und es gibt keine Unterscheidung zwischen diesen (statische und dynamische Bindung k\u00f6nnen nicht unterschieden werden, weil Die Namen werden in dieselben Werte aufgel\u00f6st. Funktioniert im folgenden Programm beispielsweise mit einer freien Variablen x (gebunden an die nicht lokale Variable x mit globalem Geltungsbereich) werden in derselben Umgebung ausgef\u00fchrt, in der x definiert ist, so ist es unerheblich, ob es sich tats\u00e4chlich um Schlie\u00dfungen handelt:x = 1nums = [1, 2, 3]def f(y): return x + ymap(f, nums)map(lambda y: x + y, nums)Dies wird meistens durch eine Funktionsr\u00fcckgabe erreicht, da die Funktion im Bereich der nicht lokalen Variablen definiert werden muss. In diesem Fall ist ihr eigener Bereich normalerweise kleiner.Dies kann auch durch variable Abschattung erreicht werden (was den Umfang der nicht lokalen Variablen verringert), obwohl dies in der Praxis weniger h\u00e4ufig ist, da es weniger n\u00fctzlich ist und von Abschattung abgeraten wird. In diesem Beispiel f kann als Schlie\u00dfung gesehen werden, weil x im K\u00f6rper von f ist an die gebunden x im globalen Namespace, nicht im x lokal zu g::x = 0def f(y): return x + ydef g(z): x = 1 # local x shadows global x return f(z)g(1) # evaluates to 1, not 2Anwendungen[edit]Die Verwendung von Verschl\u00fcssen ist mit Sprachen verbunden, in denen Funktionen erstklassige Objekte sind, in denen Funktionen als Ergebnis von Funktionen h\u00f6herer Ordnung zur\u00fcckgegeben oder als Argumente an andere Funktionsaufrufe \u00fcbergeben werden k\u00f6nnen. Wenn Funktionen mit freien Variablen erstklassig sind, f\u00fchrt die R\u00fcckgabe einer Funktion zu einem Abschluss. Dies umfasst funktionale Programmiersprachen wie Lisp und ML sowie viele moderne Multi-Paradigmen-Sprachen wie Python und Rust. Abschl\u00fcsse werden auch h\u00e4ufig bei R\u00fcckrufen verwendet, insbesondere f\u00fcr Ereignishandler, z. B. in JavaScript, wo sie f\u00fcr Interaktionen mit einer dynamischen Webseite verwendet werden.Verschl\u00fcsse k\u00f6nnen auch in einem fortlaufenden Stil verwendet werden, um den Status auszublenden. Konstrukte wie Objekte und Kontrollstrukturen k\u00f6nnen somit mit Verschl\u00fcssen implementiert werden. In einigen Sprachen kann ein Abschluss auftreten, wenn eine Funktion innerhalb einer anderen Funktion definiert ist und die innere Funktion sich auf lokale Variablen der \u00e4u\u00dferen Funktion bezieht. Zur Laufzeit, wenn die \u00e4u\u00dfere Funktion ausgef\u00fchrt wird, wird ein Abschluss gebildet, der aus dem Code der inneren Funktion und Verweisen (den Aufw\u00e4rtswerten) auf alle Variablen der \u00e4u\u00dferen Funktion besteht, die f\u00fcr den Abschluss erforderlich sind.Erstklassige Funktionen[edit]Abschl\u00fcsse werden normalerweise in Sprachen mit erstklassigen Funktionen angezeigt. Mit anderen Worten, solche Sprachen erm\u00f6glichen die \u00dcbergabe von Funktionen als Argumente, die von Funktionsaufrufen zur\u00fcckgegeben, an Variablennamen usw. gebunden werden, genau wie einfachere Typen wie Zeichenfolgen und Ganzzahlen. Betrachten Sie beispielsweise die folgende Schemafunktion:; Return a list of all books with at least THRESHOLD copies sold.(define (best-selling-books threshold) (filter (lambda (book) (>= (book-sales book) threshold)) book-list))In diesem Beispiel der Lambda-Ausdruck (lambda (book) (>= (book-sales book) threshold)) erscheint innerhalb der Funktion best-selling-books. Wenn der Lambda-Ausdruck ausgewertet wird, erstellt Scheme einen Abschluss, der aus dem Code f\u00fcr den Lambda-Ausdruck und einem Verweis auf den besteht threshold Variable, die eine freie Variable innerhalb des Lambda-Ausdrucks ist.Der Verschluss wird dann an die \u00fcbergeben filter Funktion, die es wiederholt aufruft, um zu bestimmen, welche B\u00fccher zur Ergebnisliste hinzugef\u00fcgt und welche verworfen werden sollen. Weil der Verschluss selbst einen Verweis auf hat thresholdkann diese Variable jedes Mal verwenden filter nennt es. Die Funktion filter selbst k\u00f6nnte in einer v\u00f6llig separaten Datei definiert werden.Hier ist das gleiche Beispiel, das in JavaScript, einer anderen beliebten Sprache mit Unterst\u00fctzung f\u00fcr Schlie\u00dfungen, neu geschrieben wurde:\/\/ Return a list of all books with at least 'threshold' copies sold.function bestSellingBooks(threshold) { return bookList.filter( function (book) { return book.sales >= threshold; } );}Das function Schl\u00fcsselwort wird hier anstelle von verwendet lambda, und ein Array.filter Methode[7] anstelle eines globalen filter Funktion, aber ansonsten sind die Struktur und die Wirkung des Codes gleich.Eine Funktion kann einen Abschluss erstellen und wie im folgenden Beispiel zur\u00fcckgeben:\/\/ Return a function that approximates the derivative of f\/\/ using an interval of dx, which should be appropriately small.function derivative(f, dx) { return function (x) { return (f(x + dx) - f(x)) \/ dx; };}Da der Abschluss in diesem Fall die Ausf\u00fchrung der Funktion, die ihn erstellt, \u00fcberlebt, sind die Variablen f und dx lebe weiter nach der Funktion derivative kehrt zur\u00fcck, obwohl die Ausf\u00fchrung ihren G\u00fcltigkeitsbereich verlassen hat und sie nicht mehr sichtbar sind. In Sprachen ohne Abschl\u00fcsse f\u00e4llt die Lebensdauer einer automatischen lokalen Variablen mit der Ausf\u00fchrung des Stapelrahmens zusammen, in dem diese Variable deklariert ist. In Sprachen mit Abschl\u00fcssen m\u00fcssen Variablen weiterhin vorhanden sein, solange vorhandene Abschl\u00fcsse Verweise darauf haben. Dies wird am h\u00e4ufigsten mithilfe einer Speicherbereinigung implementiert.Staatsvertretung[edit]Ein Abschluss kann verwendet werden, um eine Funktion mit einer Reihe von “privaten” Variablen zu verkn\u00fcpfen, die \u00fcber mehrere Aufrufe der Funktion bestehen bleiben. Der Bereich der Variablen umfasst nur die Closed-Over-Funktion, sodass von keinem anderen Programmcode aus darauf zugegriffen werden kann. Diese sind analog zu privaten Variablen in der objektorientierten Programmierung, und tats\u00e4chlich sind Abschl\u00fcsse analog zu einem Objekttyp, insbesondere Funktionsobjekten, mit einer einzigen \u00f6ffentlichen Methode (Funktionsaufruf) und m\u00f6glicherweise vielen privaten Variablen (den gebundenen Variablen).In zustandsbehafteten Sprachen k\u00f6nnen Schlie\u00dfungen daher verwendet werden, um Paradigmen f\u00fcr die Darstellung von Zust\u00e4nden und das Verbergen von Informationen zu implementieren, da die Aufw\u00e4rtswerte der Schlie\u00dfung (ihre geschlossenen Variablen) von unbestimmter Ausdehnung sind, sodass ein in einem Aufruf festgelegter Wert im n\u00e4chsten verf\u00fcgbar bleibt. Auf diese Weise verwendete Verschl\u00fcsse haben keine referenzielle Transparenz mehr und sind daher keine reinen Funktionen mehr. Dennoch werden sie h\u00e4ufig in unreinen Funktionssprachen wie Scheme verwendet.Andere Verwendungen[edit]Verschl\u00fcsse haben viele Verwendungszwecke:Da Schlie\u00dfungen die Auswertung verz\u00f6gern, dh nichts “tun”, bis sie aufgerufen werden, k\u00f6nnen sie zum Definieren von Kontrollstrukturen verwendet werden. Beispielsweise werden alle Standardsteuerungsstrukturen von Smalltalk, einschlie\u00dflich Zweigen (if \/ then \/ else) und Schleifen (while und for), mithilfe von Objekten definiert, deren Methoden Abschl\u00fcsse akzeptieren. Benutzer k\u00f6nnen auch einfach ihre eigenen Kontrollstrukturen definieren.In Sprachen, die Zuweisungen implementieren, k\u00f6nnen mehrere Funktionen erstellt werden, die sich in derselben Umgebung befinden, sodass sie durch \u00c4ndern dieser Umgebung privat kommunizieren k\u00f6nnen. Im Schema:(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\"Verschl\u00fcsse k\u00f6nnen verwendet werden, um Objektsysteme zu implementieren.[8]Hinweis: Einige Sprecher bezeichnen jede Datenstruktur, die eine lexikalische Umgebung bindet, als Abschluss. Der Begriff bezieht sich jedoch normalerweise speziell auf Funktionen.Implementierung und Theorie[edit]Abschl\u00fcsse werden normalerweise mit einer speziellen Datenstruktur implementiert, die einen Zeiger auf den Funktionscode sowie eine Darstellung der lexikalischen Umgebung der Funktion (dh des Satzes verf\u00fcgbarer Variablen) zum Zeitpunkt der Erstellung des Abschlusses enth\u00e4lt. Die referenzierende Umgebung bindet die nicht lokalen Namen zum Zeitpunkt der Erstellung des Abschlusses an die entsprechenden Variablen in der lexikalischen Umgebung und verl\u00e4ngert ihre Lebensdauer zus\u00e4tzlich auf mindestens die Lebensdauer des Abschlusses. Wenn der Abschluss zu einem sp\u00e4teren Zeitpunkt eingegeben wird, m\u00f6glicherweise in einer anderen lexikalischen Umgebung, wird die Funktion mit ihren nicht lokalen Variablen ausgef\u00fchrt, die sich auf die vom Abschluss erfassten Variablen beziehen, nicht auf die aktuelle Umgebung.Eine Sprachimplementierung kann vollst\u00e4ndige Schlie\u00dfungen nicht einfach unterst\u00fctzen, wenn ihr Laufzeitspeichermodell alle automatischen Variablen auf einem linearen Stapel zuweist. In solchen Sprachen werden die automatischen lokalen Variablen einer Funktion freigegeben, wenn die Funktion zur\u00fcckgegeben wird. Ein Abschluss erfordert jedoch, dass die freien Variablen, auf die er verweist, die Ausf\u00fchrung der einschlie\u00dfenden Funktion \u00fcberleben. Daher m\u00fcssen diese Variablen so zugewiesen werden, dass sie bestehen bleiben, bis sie nicht mehr ben\u00f6tigt werden, normalerweise \u00fcber die Heap-Zuweisung, und nicht mehr auf dem Stapel. Ihre Lebensdauer muss so verwaltet werden, dass sie \u00fcberleben, bis alle auf sie verweisenden Abschl\u00fcsse nicht mehr verwendet werden.Dies erkl\u00e4rt, warum normalerweise Sprachen, die Schlie\u00dfungen nativ unterst\u00fctzen, auch die Garbage Collection verwenden. Die Alternativen sind die manuelle Speicherverwaltung nicht lokaler Variablen (explizite Zuweisung auf dem Heap und Freigabe nach Abschluss) oder die Verwendung der Stapelzuweisung durch die Sprache, um zu akzeptieren, dass bestimmte Anwendungsf\u00e4lle aufgrund baumelnder Zeiger auf zu undefiniertem Verhalten f\u00fchren befreite automatische Variablen, wie in Lambda-Ausdr\u00fccken in C ++ 11[9] oder verschachtelte Funktionen in GNU C.[10] Das Funarg-Problem (oder “Funktionsargument” -Problem) beschreibt die Schwierigkeit, Funktionen als erstklassige Objekte in einer stapelbasierten Programmiersprache wie C oder C ++ zu implementieren. In \u00e4hnlicher Weise wird in D Version 1 davon ausgegangen, dass der Programmierer wei\u00df, was mit Delegaten und automatischen lokalen Variablen zu tun ist, da ihre Referenzen nach R\u00fcckkehr aus seinem Definitionsbereich ung\u00fcltig sind (automatische lokale Variablen befinden sich auf dem Stapel) – dies erlaubt immer noch viele n\u00fctzliche Funktionsmuster, aber f\u00fcr komplexe F\u00e4lle erfordert explizite Heap-Zuordnung f\u00fcr Variablen. D Version 2 l\u00f6ste dieses Problem, indem erkannt wurde, welche Variablen auf dem Heap gespeichert werden m\u00fcssen, und f\u00fchrte eine automatische Zuordnung durch. Da D die Garbage Collection verwendet, ist es in beiden Versionen nicht erforderlich, die Verwendung von Variablen bei der \u00dcbergabe zu verfolgen.In streng funktionalen Sprachen mit unver\u00e4nderlichen Daten (z.B Erlang) ist die automatische Speicherverwaltung (Garbage Collection) sehr einfach zu implementieren, da in den Variablenreferenzen keine m\u00f6glichen Zyklen vorhanden sind. In Erlang werden beispielsweise alle Argumente und Variablen auf dem Heap zugewiesen, aber Verweise darauf werden zus\u00e4tzlich auf dem Stapel gespeichert. Nach der R\u00fcckkehr einer Funktion sind die Referenzen weiterhin g\u00fcltig. Die Heap-Reinigung erfolgt durch einen inkrementellen Garbage Collector.In ML haben lokale Variablen einen lexikalischen G\u00fcltigkeitsbereich und definieren daher ein stapelartiges Modell. Da sie jedoch an Werte und nicht an Objekte gebunden sind, kann eine Implementierung diese Werte auf eine Weise in die Datenstruktur des Abschlusses kopieren, die f\u00fcr sie unsichtbar ist der Programmierer.Scheme, das \u00fcber ein ALGOL-\u00e4hnliches lexikalisches Scope-System mit dynamischen Variablen und Garbage Collection verf\u00fcgt, verf\u00fcgt nicht \u00fcber ein Stack-Programmiermodell und leidet nicht unter den Einschr\u00e4nkungen stapelbasierter Sprachen. Verschl\u00fcsse werden nat\u00fcrlich im Schema ausgedr\u00fcckt. Das Lambda-Formular enth\u00e4lt den Code, und die freien Variablen seiner Umgebung bleiben im Programm erhalten, solange auf sie m\u00f6glicherweise zugegriffen werden kann, und k\u00f6nnen daher so frei wie jeder andere Scheme-Ausdruck verwendet werden.[citation needed]Abschl\u00fcsse sind eng mit Akteuren im Actor-Modell der gleichzeitigen Berechnung verwandt, wobei die Werte in der lexikalischen Umgebung der Funktion aufgerufen werden Bekannte. Ein wichtiges Problem bei Schlie\u00dfungen in gleichzeitigen Programmiersprachen ist, ob die Variablen in einer Schlie\u00dfung aktualisiert werden k\u00f6nnen und wenn ja, wie diese Aktualisierungen synchronisiert werden k\u00f6nnen. Schauspieler bieten eine L\u00f6sung.[11]Verschl\u00fcsse sind eng mit Funktionsobjekten verbunden. Die Umwandlung von ersteren zu letzteren wird als Defunktionalisierung oder Lambda-Heben bezeichnet. siehe auch Verschlussumwandlung.[citation needed]Unterschiede in der Semantik[edit]Lexikalische Umgebung[edit]Da verschiedene Sprachen nicht immer eine gemeinsame Definition der lexikalischen Umgebung haben, k\u00f6nnen auch ihre Definitionen des Abschlusses variieren. Die allgemein verbreitete minimalistische Definition der lexikalischen Umgebung definiert sie als eine Menge aller Bindungen von Variablen im Bereich, und das ist auch das, was Abschl\u00fcsse in jeder Sprache erfassen m\u00fcssen. Die Bedeutung einer variablen Bindung unterscheidet sich jedoch ebenfalls. In imperativen Sprachen binden Variablen an relative Speicherorte, an denen Werte gespeichert werden k\u00f6nnen. Obwohl sich die relative Position einer Bindung zur Laufzeit nicht \u00e4ndert, kann sich der Wert an der gebundenen Position \u00e4ndern. In solchen Sprachen wird, da das Schlie\u00dfen die Bindung erfasst, jede Operation an der Variablen, unabh\u00e4ngig davon, ob sie vom Schlie\u00dfen ausgeht oder nicht, an demselben relativen Speicherort ausgef\u00fchrt. Dies wird oft als Erfassung der Variablen “als Referenz” bezeichnet. Hier ist ein Beispiel, das das Konzept in ECMAScript veranschaulicht, einer solchen Sprache:\/\/ ECMAScriptvar f, g;function foo() { var x; f = function() { return ++x; }; g = function() { return --x; }; x = 1; alert('inside foo, call to f(): ' + f());}foo(); \/\/ 2alert('call to g(): ' + g()); \/\/ 1 (--x)alert('call to g(): ' + g()); \/\/ 0 (--x)alert('call to f(): ' + f()); \/\/ 1 (++x)alert('call to f(): ' + f()); \/\/ 2 (++x)Funktion foo und die Verschl\u00fcsse, auf die sich Variablen beziehen f und g Alle verwenden denselben relativen Speicherort, der durch die lokale Variable gekennzeichnet ist x.In einigen F\u00e4llen kann das obige Verhalten unerw\u00fcnscht sein und es ist notwendig, einen anderen lexikalischen Verschluss zu binden. Auch in ECMAScript w\u00fcrde dies mit dem erfolgen Function.bind().Beispiel 1: Verweis auf eine ungebundene Variable[edit][12]var module = { x: 42, getX: function() {return this.x; }}var unboundGetX = module.getX;console.log(unboundGetX()); \/\/ The function gets invoked at the global scope\/\/ emits undefined as 'x' is not specified in global scope.var boundGetX = unboundGetX.bind(module); \/\/ specify object module as the closureconsole.log(boundGetX()); \/\/ emits 42Beispiel 2: Versehentlicher Verweis auf eine gebundene Variable[edit]In diesem Beispiel w\u00fcrde das erwartete Verhalten darin bestehen, dass jeder Link beim Klicken seine ID ausgibt. Da die Variable ‘e’ jedoch an den oben genannten Bereich gebunden und beim Klicken verz\u00f6gert ausgewertet wird, gibt jedes Ereignis beim Klicken die ID des letzten Elements in ‘elements’ aus, das am Ende der for-Schleife gebunden ist.[13]var elements= document.getElementsByTagName('a');\/\/Incorrect: e is bound to the function containing the 'for' loop, not the closure of \"handle\"for (var e in elements){ e.onclick=function handle(){ alert(e.id);} }Auch hier variabel e m\u00fcsste durch den Umfang des Blocks mit gebunden werden handle.bind(this) oder der let Stichwort.Andererseits binden viele funktionale Sprachen wie ML Variablen direkt an Werte. In diesem Fall besteht keine Notwendigkeit, den Status zwischen Abschl\u00fcssen zu teilen, da es keine M\u00f6glichkeit gibt, den Wert der Variablen nach ihrer Bindung zu \u00e4ndern. Sie verwenden lediglich dieselben Werte. Dies wird oft als Erfassung der Variablen “nach Wert” bezeichnet. Die lokalen und anonymen Klassen von Java fallen ebenfalls in diese Kategorie – sie erfordern erfasste lokale Variablen finalDies bedeutet auch, dass kein Status geteilt werden muss.In einigen Sprachen k\u00f6nnen Sie w\u00e4hlen, ob Sie den Wert einer Variablen oder ihren Speicherort erfassen m\u00f6chten. In C ++ 11 werden erfasste Variablen beispielsweise entweder mit deklariert [&], was bedeutet, durch Referenz oder mit erfasst [=], was bedeutet, durch Wert erfasst.Eine weitere Untergruppe, faule Funktionssprachen wie Haskell, binden Variablen eher an Ergebnisse zuk\u00fcnftiger Berechnungen als an Werte. Betrachten Sie dieses Beispiel in Haskell:-- Haskellfoo :: Fractional a => a -> a -> (a -> a)foo x y = (z -> z + r) where r = x \/ yf :: Fractional a => a -> af = foo 1 0main = print (f 123)Die Bindung von r erfasst durch den in der Funktion definierten Verschluss foo ist zur Berechnung (x \/ y)– was in diesem Fall zur Division durch Null f\u00fchrt. Da jedoch die Berechnung erfasst wird und nicht der Wert, tritt der Fehler nur dann auf, wenn der Abschluss aufgerufen wird, und versucht tats\u00e4chlich, die erfasste Bindung zu verwenden.Schlie\u00dfung verlassen[edit]Noch mehr Unterschiede manifestieren sich im Verhalten anderer Konstrukte mit lexikalischem Umfang, wie z return, break und continue Aussagen. Solche Konstrukte k\u00f6nnen im Allgemeinen als Aufruf einer Escape-Fortsetzung betrachtet werden, die durch eine einschlie\u00dfende Steueranweisung festgelegt wurde (im Fall von break und continueF\u00fcr eine solche Interpretation m\u00fcssen Schleifenkonstrukte in Bezug auf rekursive Funktionsaufrufe ber\u00fccksichtigt werden. In einigen Sprachen, wie z. B. ECMAScript, return bezieht sich auf die Fortsetzung, die durch den lexikalisch innersten Verschluss in Bezug auf die Aussage hergestellt wird – also a return Innerhalb eines Abschlusses wird die Kontrolle an den Code \u00fcbertragen, der sie aufgerufen hat. In Smalltalk jedoch der oberfl\u00e4chlich \u00e4hnliche Operator ^ Ruft die f\u00fcr den Methodenaufruf festgelegte Escape-Fortsetzung auf und ignoriert die Escape-Fortsetzungen aller dazwischen liegenden verschachtelten Abschl\u00fcsse. Die Escape-Fortsetzung eines bestimmten Abschlusses kann in Smalltalk nur implizit aufgerufen werden, wenn das Ende des Code des Abschlusses erreicht ist. Die folgenden Beispiele in ECMAScript und Smalltalk verdeutlichen den Unterschied:\"Smalltalk\"foo | xs | xs := #(1 2 3 4). xs do: [:x | ^x]. ^0bar Transcript show: (self foo printString) \"prints 1\"\/\/ ECMAScriptfunction foo() { var xs = [1, 2, 3, 4]; xs.forEach(function (x) { return x; }); return 0;}alert(foo()); \/\/ prints 0Die obigen Codefragmente verhalten sich anders als das Smalltalk ^ Operator und das JavaScript return Betreiber sind nicht analog. Im ECMAScript-Beispiel return x verl\u00e4sst den inneren Verschluss, um eine neue Iteration des zu beginnen forEach Schleife, w\u00e4hrend im Smalltalk-Beispiel ^x bricht die Schleife ab und kehrt von der Methode zur\u00fcck foo.Common Lisp bietet ein Konstrukt, das eine der oben genannten Aktionen ausdr\u00fccken kann: Lisp (return-from foo x) verh\u00e4lt sich wie Smalltalk ^xw\u00e4hrend Lisp (return-from nil x) verh\u00e4lt sich wie JavaScript return x. Smalltalk erm\u00f6glicht es daher, dass eine erfasste Escape-Fortsetzung das Ausma\u00df \u00fcberlebt, in dem sie erfolgreich aufgerufen werden kann. Erw\u00e4gen:\"Smalltalk\"foo ^[ :x | ^x ]bar | f | f := self foo. f value: 123 \"error!\"Wenn der Verschluss von der Methode zur\u00fcckgegeben wird foo Wenn es aufgerufen wird, versucht es, einen Wert aus dem Aufruf von zur\u00fcckzugeben foo das schuf die Schlie\u00dfung. Da dieser Aufruf bereits zur\u00fcckgegeben wurde und das Aufrufmodell der Smalltalk-Methode nicht der Spaghetti-Stack-Disziplin folgt, um mehrere R\u00fcckgaben zu erm\u00f6glichen, f\u00fchrt dieser Vorgang zu einem Fehler.Einige Sprachen, wie z. B. Ruby, erm\u00f6glichen es dem Programmierer, den Weg zu w\u00e4hlen return ist gefangen. Ein Beispiel in Ruby:# Ruby# Closure using a Procdef foo f = Proc.new { return \"return from foo from inside proc\" } f.call # control leaves foo here return \"return from foo\"end# Closure using a lambdadef bar f = lambda { return \"return from lambda\" } f.call # control does not leave bar here return \"return from bar\"endputs foo # prints \"return from foo from inside proc\"puts bar # prints \"return from bar\"Beide Proc.new und lambda In diesem Beispiel gibt es M\u00f6glichkeiten, einen Abschluss zu erstellen, aber die Semantik der so erstellten Abschl\u00fcsse unterscheidet sich in Bezug auf die return Erkl\u00e4rung.In Schema, Definition und Umfang der return Die Steueranweisung ist explizit (und wird im Beispiel nur willk\u00fcrlich als “return” bezeichnet). Das Folgende ist eine direkte \u00dcbersetzung des Ruby-Beispiels.; Scheme(define call\/cc call-with-current-continuation)(define (foo) (call\/cc (lambda (return) (define (f) (return \"return from foo from inside proc\")) (f) ; control leaves foo here (return \"return from foo\"))))(define (bar) (call\/cc (lambda (return) (define (f) (call\/cc (lambda (return) (return \"return from lambda\")))) (f) ; control does not leave bar here (return \"return from bar\"))))(display (foo)) ; prints \"return from foo from inside proc\"(newline)(display (bar)) ; prints \"return from bar\"Verschlussartige Konstrukte[edit]Einige Sprachen verf\u00fcgen \u00fcber Funktionen, die das Verhalten von Schlie\u00dfungen simulieren. In Sprachen wie Java, C ++, Objective-C, C #, VB.NET und D sind diese Funktionen das Ergebnis des objektorientierten Paradigmas der Sprache.R\u00fcckrufe (C)[edit]Einige C-Bibliotheken unterst\u00fctzen R\u00fcckrufe. Dies wird manchmal implementiert, indem beim Registrieren des R\u00fcckrufs bei der Bibliothek zwei Werte angegeben werden: ein Funktionszeiger und ein separater void* Zeiger auf beliebige Daten nach Wahl des Benutzers. Wenn die Bibliothek die R\u00fcckruffunktion ausf\u00fchrt, leitet sie den Datenzeiger weiter. Auf diese Weise kann der R\u00fcckruf den Status beibehalten und auf Informationen verweisen, die zum Zeitpunkt der Registrierung in der Bibliothek erfasst wurden. Die Redewendung \u00e4hnelt Verschl\u00fcssen in der Funktionalit\u00e4t, jedoch nicht in der Syntax. Dasvoid* Der Zeiger ist nicht typsicher, daher unterscheidet sich dieses C-Idiom von typsicheren Verschl\u00fcssen in C #, Haskell oder ML.R\u00fcckrufe werden h\u00e4ufig in GUI-Widget-Toolkits verwendet, um die ereignisgesteuerte Programmierung zu implementieren, indem allgemeine Funktionen grafischer Widgets (Men\u00fcs, Schaltfl\u00e4chen, Kontrollk\u00e4stchen, Schieberegler, Drehfelder usw.) mit anwendungsspezifischen Funktionen verkn\u00fcpft werden, die das gew\u00fcnschte spezifische Verhalten f\u00fcr die Anwendung implementieren.Verschachtelte Funktion und Funktionszeiger (C)[edit]Mit einer gcc-Erweiterung a verschachtelte Funktion kann verwendet werden und ein Funktionszeiger kann Schlie\u00dfungen emulieren, vorausgesetzt, die Funktion verl\u00e4sst den enthaltenen Bereich nicht. Das folgende Beispiel ist ung\u00fcltig, weil adder ist eine Definition der obersten Ebene (abh\u00e4ngig von der Compilerversion kann sie zu einem korrekten Ergebnis f\u00fchren, wenn sie ohne Optimierung kompiliert wird, dh bei -O0):#include typedef int (*fn_int_to_int)(int); \/\/ type of function int->intfn_int_to_int adder(int number) { int add (int value) { return value + number; } return &add; \/\/ & operator is optional here because the name of a function in C is a pointer pointing on itself}int main(void) { fn_int_to_int add10 = adder(10); printf(\"%dn\", add10(1)); return 0;}Aber sich bewegen adder (und optional die typedef) im main macht es g\u00fcltig:#include int main(void) { typedef int (*fn_int_to_int)(int); \/\/ type of function int->int fn_int_to_int adder(int number) { int add (int value) { return value + number; } return add; } fn_int_to_int add10 = adder(10); printf(\"%dn\", add10(1)); return 0;}Wenn ausgef\u00fchrt, wird dies jetzt gedruckt 11 wie erwartet.Lokale Klassen und Lambda-Funktionen (Java)[edit]Mit Java k\u00f6nnen Klassen innerhalb von Methoden definiert werden. Diese nennt man lokale Klassen. Wenn solche Klassen nicht benannt sind, werden sie als bezeichnet anonyme Klassen (oder anonym innere Klassen). Eine lokale Klasse (entweder benannt oder anonym) kann sich auf Namen in lexikalisch einschlie\u00dfenden Klassen oder auf schreibgesch\u00fctzte Variablen (markiert als) beziehen final) in der lexikalisch einschlie\u00dfenden Methode.class CalculationWindow extends JFrame { private volatile int result; ... public void calculateInSeparateThread(final URI uri) { \/\/ The expression \"new Runnable() { ... }\" is an anonymous class implementing the 'Runnable' interface. new Thread( new Runnable() { void run() { \/\/ It can read final local variables: calculate(uri); \/\/ It can access private fields of the enclosing class: result = result + 10; } } ).start(); }}Die Erfassung von final Mit Variablen k\u00f6nnen Sie Variablen nach Wert erfassen. Auch wenn die Variable, die Sie erfassen m\u00f6chten, nichtfinalk\u00f6nnen Sie es jederzeit in ein tempor\u00e4res kopieren final Variable kurz vor der Klasse.Das Erfassen von Variablen als Referenz kann mithilfe von a emuliert werden final Verweis auf einen ver\u00e4nderlichen Container, z. B. ein Einzelelementarray. Die lokale Klasse kann den Wert der Containerreferenz selbst nicht \u00e4ndern, aber den Inhalt des Containers.Mit dem Aufkommen der Lambda-Ausdr\u00fccke von Java 8[14] Durch das Schlie\u00dfen wird der obige Code wie folgt ausgef\u00fchrt:class CalculationWindow extends JFrame { private volatile int result; ... public void calculateInSeparateThread(final URI uri) { \/\/ The code () -> { \/* code *\/ } is a closure. new Thread(() -> { calculate(uri); result = result + 10; }).start(); }}Lokale Klassen sind eine der Arten innerer Klassen, die im Hauptteil einer Methode deklariert werden. Java unterst\u00fctzt auch innere Klassen, die als deklariert sind nicht statische Mitglieder einer einschlie\u00dfenden Klasse.[15] Sie werden normalerweise nur als “innere Klassen” bezeichnet.[16] Diese werden im Hauptteil der einschlie\u00dfenden Klasse definiert und haben vollen Zugriff auf Instanzvariablen der einschlie\u00dfenden Klasse. Aufgrund ihrer Bindung an diese Instanzvariablen kann eine innere Klasse nur mit einer expliziten Bindung an eine Instanz der einschlie\u00dfenden Klasse unter Verwendung einer speziellen Syntax instanziiert werden.[17]public class EnclosingClass { \/* Define the inner class *\/ public class InnerClass { public int incrementAndReturnCounter() { return counter++; } } private int counter; { counter = 0; } public int getCounter() { return counter; } public static void main(String[] args) { EnclosingClass enclosingClassInstance = new EnclosingClass(); \/* Instantiate the inner class, with binding to the instance *\/ EnclosingClass.InnerClass innerClassInstance = enclosingClassInstance.new InnerClass(); for (int i = enclosingClassInstance.getCounter(); (i = innerClassInstance.incrementAndReturnCounter()) s.length(); System.out.println( length.apply(\"Hello, world!\") ); \/\/ Will print 13.}Bl\u00f6cke (C, C ++, Objective-C 2.0)[edit]Apple f\u00fchrte Bl\u00f6cke, eine Form des Schlie\u00dfens, als nicht standardm\u00e4\u00dfige Erweiterung in C, C ++, Objective-C 2.0 und in Mac OS X 10.6 “Snow Leopard” und iOS 4.0 ein. Apple stellte ihre Implementierung f\u00fcr die GCC- und Clang-Compiler zur Verf\u00fcgung.Zeiger zum Blockieren und Blockieren von Literalen sind mit gekennzeichnet ^. Normale lokale Variablen werden beim Erstellen des Blocks nach Wert erfasst und sind innerhalb des Blocks schreibgesch\u00fctzt. Variablen, die als Referenz erfasst werden sollen, sind mit gekennzeichnet __block. Bl\u00f6cke, die au\u00dferhalb des Bereichs verbleiben m\u00fcssen, in dem sie erstellt wurden, m\u00fcssen m\u00f6glicherweise kopiert werden.[18][19]typedef int (^IntBlock)();IntBlock downCounter(int start) {\t __block int i = start;\t return [[ ^int() {\t\t return i--;\t } copy] autorelease];}IntBlock f = downCounter(5);NSLog(@\"%d\", f());NSLog(@\"%d\", f());NSLog(@\"%d\", f());Delegierte (C #, VB.NET, D)[edit]Anonyme C # -Methoden und Lambda-Ausdr\u00fccke unterst\u00fctzen das Schlie\u00dfen:var data = new[] {1, 2, 3, 4};var multiplier = 2;var result = data.Select(x => x * multiplier);Visual Basic .NET, das viele \u00e4hnliche Sprachfunktionen wie C # bietet, unterst\u00fctzt auch Lambda-Ausdr\u00fccke mit Abschl\u00fcssen:Dim data = {1, 2, 3, 4}Dim multiplier = 2Dim result = data.Select(Function(x) x * multiplier)In D werden Closures von Delegaten implementiert, einem Funktionszeiger, der mit einem Kontextzeiger gepaart ist (z. B. einer Klasseninstanz oder einem Stapelrahmen auf dem Heap bei Closures).auto test1() { int a = 7; return delegate() { return a + 3; }; \/\/ anonymous delegate construction}auto test2() { int a = 20; int foo() { return a + 5; } \/\/ inner function return &foo; \/\/ other way to construct delegate}void bar() { auto dg = test1(); dg(); \/\/ =10 \/\/ ok, test1.a is in a closure and still exists dg = test2(); dg(); \/\/ =25 \/\/ ok, test2.a is in a closure and still exists}D Version 1 hat eine begrenzte Verschlussunterst\u00fctzung. Zum Beispiel funktioniert der obige Code nicht richtig, da sich die Variable a auf dem Stapel befindet und nach der R\u00fcckkehr von test () die Verwendung nicht mehr g\u00fcltig ist (wenn Sie foo h\u00f6chstwahrscheinlich \u00fcber dg () aufrufen, wird a ‘zur\u00fcckgegeben. zuf\u00e4llige ‘ganze Zahl). Dies kann gel\u00f6st werden, indem die Variable ‘a’ explizit auf dem Heap zugewiesen wird oder indem Strukturen oder Klassen verwendet werden, um alle erforderlichen geschlossenen Variablen zu speichern und einen Delegaten aus einer Methode zu erstellen, die denselben Code implementiert. Abschl\u00fcsse k\u00f6nnen an andere Funktionen \u00fcbergeben werden, sofern sie nur verwendet werden, solange die referenzierten Werte noch g\u00fcltig sind (z. B. Aufrufen einer anderen Funktion mit einem Abschluss als R\u00fcckrufparameter) und zum Schreiben von generischem Datenverarbeitungscode n\u00fctzlich sind, daher diese Einschr\u00e4nkung In der Praxis ist dies oft kein Problem.Diese Einschr\u00e4nkung wurde in D Version 2 behoben – die Variable ‘a’ wird automatisch auf dem Heap zugewiesen, da sie in der inneren Funktion verwendet wird, und ein Delegat dieser Funktion kann sich dem aktuellen Bereich entziehen (durch Zuweisung zu dg oder return). Alle anderen lokalen Variablen (oder Argumente), auf die nicht von Delegaten verwiesen wird oder die nur von Delegierten referenziert werden, die sich dem aktuellen Bereich nicht entziehen, verbleiben auf dem Stapel, der einfacher und schneller als die Heap-Zuweisung ist. Gleiches gilt f\u00fcr die Klassenmethoden von inner, die auf die Variablen einer Funktion verweisen.Funktionsobjekte (C ++)[edit]C ++ erm\u00f6glicht das Definieren von Funktionsobjekten durch \u00dcberladen operator(). Diese Objekte verhalten sich \u00e4hnlich wie Funktionen in einer funktionalen Programmiersprache. Sie k\u00f6nnen zur Laufzeit erstellt werden und den Status enthalten, erfassen jedoch nicht implizit lokale Variablen wie Schlie\u00dfungen. Ab der Revision von 2011 unterst\u00fctzt die C ++ – Sprache auch Closures, eine Art Funktionsobjekt, das automatisch aus einem speziellen Sprachkonstrukt namens erstellt wird Lambda-Ausdruck. Ein C ++ – Abschluss kann seinen Kontext entweder durch Speichern von Kopien der Variablen, auf die zugegriffen wird, als Mitglieder des Abschlussobjekts oder durch Referenz erfassen. Im letzteren Fall, wenn das Abschlussobjekt den Bereich eines referenzierten Objekts verl\u00e4sst und dessen aufruft operator() verursacht undefiniertes Verhalten, da C ++ – Schlie\u00dfungen die Lebensdauer ihres Kontexts nicht verl\u00e4ngern.void foo(string myname) { int y; vector n; \/\/ ... auto i = std::find_if(n.begin(), n.end(), \/\/ this is the lambda expression: [&](const string& s) { return s != myname && s.size() > y; } ); \/\/ 'i' is now either 'n.end()' or points to the first string in 'n' \/\/ which is not equal to 'myname' and whose length is greater than 'y'}Inline-Agenten (Eiffel)[edit]Eiffel enth\u00e4lt Inline-Agenten, die Schlie\u00dfungen definieren. Ein Inline-Agent ist ein Objekt, das eine Routine darstellt und durch Angabe des Codes der Routine inline definiert wird. Zum Beispiel inok_button.click_event.subscribe (\tagent (x, y: INTEGER) do\t\tmap.country_at_coordinates (x, y).display\tend)das Argument zu subscribe ist ein Agent, der eine Prozedur mit zwei Argumenten darstellt; Die Prozedur findet das Land an den entsprechenden Koordinaten und zeigt es an. Der gesamte Agent hat den Ereignistyp “abonniert” click_event F\u00fcr eine bestimmte Schaltfl\u00e4che wird die Prozedur ausgef\u00fchrt, wenn eine Instanz des Ereignistyps auf dieser Schaltfl\u00e4che auftritt – da ein Benutzer auf die Schaltfl\u00e4che geklickt hat -, wobei die Mauskoordinaten als Argumente f\u00fcr \u00fcbergeben werden x und y.Die Hauptbeschr\u00e4nkung von Eiffel-Agenten, die sie von Abschl\u00fcssen in anderen Sprachen unterscheidet, besteht darin, dass sie nicht auf lokale Variablen aus dem umschlie\u00dfenden Bereich verweisen k\u00f6nnen. Diese Entwurfsentscheidung hilft dabei, Mehrdeutigkeiten zu vermeiden, wenn \u00fcber einen lokalen Variablenwert in einem Abschluss gesprochen wird. Sollte dies der neueste Wert der Variablen oder der Wert sein, der beim Erstellen des Agenten erfasst wird? Nur Current (ein Verweis auf das aktuelle Objekt, analog zu this In Java) k\u00f6nnen die Funktionen und Argumente des Agenten selbst \u00fcber den Agentenk\u00f6rper aufgerufen werden. Die Werte der \u00e4u\u00dferen lokalen Variablen k\u00f6nnen \u00fcbergeben werden, indem dem Agenten zus\u00e4tzliche geschlossene Operanden bereitgestellt werden.C ++ Builder __closure reserviertes Wort[edit]Embarcadero C ++ Builder stellt das Reservewort __closure bereit, um einen Zeiger auf eine Methode mit einer \u00e4hnlichen Syntax wie ein Funktionszeiger bereitzustellen.[20]In Standard C k\u00f6nnte man a schreiben typedef f\u00fcr einen Zeiger auf einen Funktionstyp mit der folgenden Syntax:typedef void (*TMyFunctionPointer)( void );In \u00e4hnlicher Weise k\u00f6nnen Sie a deklarieren typedef f\u00fcr einen Zeiger auf eine Methode mit der folgenden Syntax:typedef void (__closure *TMyMethodPointer)();Siehe auch[edit]^ Die Funktion kann als Referenz auf eine Funktion gespeichert werden, beispielsweise als Funktionszeiger.^ Diese Namen beziehen sich am h\u00e4ufigsten auf Werte, ver\u00e4nderbare Variablen oder Funktionen, k\u00f6nnen aber auch andere Entit\u00e4ten wie Konstanten, Typen, Klassen oder Beschriftungen sein.Verweise[edit]^ Sussman und Steele. “Schema: Ein Interpreter f\u00fcr den erweiterten Lambda-Kalk\u00fcl”. “… eine Datenstruktur, die einen Lambda-Ausdruck enth\u00e4lt, und eine Umgebung, die verwendet werden soll, wenn dieser Lambda-Ausdruck auf Argumente angewendet wird.” ((Wikisource)^ David A. Turner (2012). “Einige Geschichte funktionaler Programmiersprachen”. Trends in der funktionalen Programmierung ’12. Abschnitt 2, Anmerkung 8 enth\u00e4lt die Behauptung \u00fcber M-Ausdr\u00fccke.^ PJ Landin (1964), Die mechanische Bewertung von Ausdr\u00fccken^ Joel Moses (Juni 1970), Die Funktion von FUNCTION in LISP oder warum das FUNARG-Problem als Umgebungsproblem bezeichnet werden sollte, hdl:1721,1 \/ 5854, AI Memo 199, Eine n\u00fctzliche Metapher f\u00fcr den Unterschied zwischen FUNCTION und QUOTE in LISP besteht darin, QUOTE als por\u00f6se oder offene Abdeckung der Funktion zu betrachten, da freie Variablen in die aktuelle Umgebung gelangen. FUNCTION wirkt als geschlossene oder nicht por\u00f6se Abdeckung (daher der von Landin verwendete Begriff “Verschluss”). Daher sprechen wir von “offenen” Lambda-Ausdr\u00fccken (Funktionen in LISP sind normalerweise Lambda-Ausdr\u00fccke) und “geschlossenen” Lambda-Ausdr\u00fccken. […] Mein Interesse am Umweltproblem begann, als Landin, der ein tiefes Verst\u00e4ndnis f\u00fcr das Problem hatte, zwischen 1966 und 1967 das MIT besuchte. Ich erkannte dann die Entsprechung zwischen den FUNARG-Listen, die das Ergebnis der Bewertung “geschlossener” Lambda-Ausdr\u00fccke in LISP und den Lambda-Verschl\u00fcssen von ISWIM sind.^ \u00c5ke Wikstr\u00f6m (1987). Funktionsprogrammierung mit Standard ML. ISBN 0-13-331968-7. Der Grund, warum es als “Abschluss” bezeichnet wird, ist, dass ein Ausdruck, der freie Variablen enth\u00e4lt, als “offener” Ausdruck bezeichnet wird. Wenn Sie ihm die Bindungen seiner freien Variablen zuordnen, schlie\u00dfen Sie ihn.^ Gerald Jay Sussman und Guy L. Steele, Jr. (Dezember 1975), Schema: Ein Interpreter f\u00fcr den erweiterten Lambda-Kalk\u00fcl, AI Memo 349^ “array.filter”. Mozilla Developer Center. 10. Januar 2010. Abgerufen 9. Februar 2010.^ “Re: FP, OO und Beziehungen. Trumpft jemand die anderen?”. 29. Dezember 1999. Archiviert von das Original am 26. Dezember 2008. Abgerufen 23. Dezember 2008.^ Lambda-Ausdr\u00fccke und Verschl\u00fcsse C ++ Standards Committee. 29. Februar 2008.^ GCC Handbuch, 6.4 Verschachtelte Funktionen, “Wenn Sie versuchen, die verschachtelte Funktion \u00fcber ihre Adresse aufzurufen, nachdem die enthaltende Funktion beendet wurde, bricht die H\u00f6lle los. Wenn Sie versuchen, sie aufzurufen, nachdem eine enthaltende Bereichsebene beendet wurde, und wenn sie sich auf einige der Variablen bezieht, die nicht mehr vorhanden sind.” Im Bereich haben Sie vielleicht Gl\u00fcck, aber es ist nicht ratsam, das Risiko einzugehen. Wenn sich die verschachtelte Funktion jedoch nicht auf etwas bezieht, das au\u00dferhalb des Bereichs liegt, sollten Sie sicher sein. “^ Grundlagen der Schauspielersemantik Will Clinger. MIT Mathematics Doktorarbeit. Juni 1981.^ “Function.prototype.bind ()”. MDN-Webdokumente. Abgerufen 20. November 2018.^ “Verschl\u00fcsse”. MDN-Webdokumente. Abgerufen 20. November 2018.^ “Lambda-Ausdr\u00fccke (Die Java-Tutorials)”.^ “Verschachtelte, innere, Mitglieder- und Top-Level-Klassen”.^ “Beispiel f\u00fcr eine innere Klasse (Die Java-Tutorials> Lernen der Java-Sprache> Klassen und Objekte)”.^ “Verschachtelte Klassen (Die Java-Tutorials> Lernen der Java-Sprache> Klassen und Objekte)”.^ Apple Inc. “Blockiert Programmierthemen”. Abgerufen 8. M\u00e4rz 2011.^ Joachim Bengtsson (7. Juli 2010). “Programmieren mit C-Bl\u00f6cken auf Apple-Ger\u00e4ten”. Archiviert von das Original am 25. Oktober 2010. Abgerufen 18. September 2010.^ Die vollst\u00e4ndige Dokumentation finden Sie unter http:\/\/docwiki.embarcadero.com\/RADStudio\/Rio\/en\/ClosureExterne Links[edit]"},{"@context":"http:\/\/schema.org\/","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"item":{"@id":"https:\/\/wiki.edu.vn\/wiki15\/#breadcrumbitem","name":"Enzyklop\u00e4die"}},{"@type":"ListItem","position":2,"item":{"@id":"https:\/\/wiki.edu.vn\/wiki15\/2020\/12\/24\/schliesung-computerprogrammierung-wikipedia\/#breadcrumbitem","name":"Schlie\u00dfung (Computerprogrammierung) – Wikipedia"}}]}]