In Programmiersprachen sind Verschlüsse ein beliebtes und oft gewünschtes Merkmal. Wikipedia sagt (Hervorhebung von mir):
In der Informatik ist ein Closure (...) eine Funktion zusammen mit einer Referenzierungsumgebung für die nicht lokalen Variablen dieser Funktion. Ein Closure ermöglicht es einer Funktion, auf Variablen außerhalb ihres unmittelbaren lexikalischen Bereichs zuzugreifen.
Ein Closure ist also im Wesentlichen ein (anonymer?) Funktionswert, der Variablen außerhalb seines eigenen Gültigkeitsbereichs verwenden kann. Nach meiner Erfahrung bedeutet dies, dass auf Variablen zugegriffen werden kann, die sich an ihrem Definitionspunkt im Gültigkeitsbereich befinden.
In der Praxis scheint sich das Konzept jedoch zumindest außerhalb der funktionalen Programmierung zu unterscheiden. Verschiedene Sprachen implementieren unterschiedliche Semantiken, es scheint sogar Meinungsverschiedenheiten zu geben. Viele Programmierer scheinen nicht zu wissen, was Abschlüsse sind, und betrachten sie nur als anonyme Funktionen.
Auch bei der Umsetzung von Schließungen scheinen große Hürden zu bestehen. Am bemerkenswertesten ist, dass Java 7 sie enthalten sollte, aber die Funktion wurde auf eine zukünftige Version zurückgesetzt.
Warum sind Verschlüsse so schwer zu verstehen und zu realisieren? Dies ist eine zu weit gefasste und vage Frage, daher möchte ich mich auf diese miteinander verbundenen Fragen konzentrieren:
- Gibt es Probleme beim Ausdruck von Abschlüssen in gemeinsamen semantischen Formalismen (kleine Schritte, große Schritte, ...)?
- Sind vorhandene Typsysteme nicht für Verschlüsse geeignet und können nicht einfach erweitert werden?
- Ist es problematisch, Verschlüsse an eine herkömmliche stapelbasierte Verfahrensübersetzung anzupassen?
Beachten Sie, dass sich die Frage hauptsächlich auf prozedurale, objektorientierte und Skriptsprachen im Allgemeinen bezieht. Soweit ich weiß, haben funktionale Sprachen keine Probleme.
quelle
Antworten:
Darf ich Sie auf die Wikipedia-Seite des Funarg-Problems weiterleiten ? Zumindest haben die Compiler-Leute so auf das Problem der Closure-Implementierung verwiesen.
Obwohl diese Definition sinnvoll ist, hilft sie nicht, das Problem der Implementierung erstklassiger Funktionen in einer traditionellen Sprache auf Laufzeitstapelbasis zu beschreiben. Wenn es um Implementierungsprobleme geht, können erstklassige Funktionen grob in zwei Klassen unterteilt werden:
Der erste Fall (downwards funargs) ist nicht so schwer zu implementieren und kann auch in älteren prozeduralen Sprachen wie Algol, C und Pascal gefunden werden. C umgeht das Problem, da es keine verschachtelten Funktionen zulässt, aber Algol und Pascal die erforderliche Buchhaltung durchführen, damit innere Funktionen auf die Stapelvariablen der äußeren Funktion verweisen können.
Der zweite Fall (Aufwärts-Funargs) erfordert andererseits, dass Aktivierungsdatensätze außerhalb des Stapels im Heap gespeichert werden. Dies bedeutet, dass es sehr leicht ist, Speicherressourcen zu verlieren, wenn die Sprachlaufzeit keinen Garbage Collector enthält. Während heute fast alles Müll ist, ist das Erfordernis einer Müllabfuhr immer noch eine bedeutende Designentscheidung, und dies war vor einiger Zeit noch wichtiger.
Wenn ich mich richtig erinnere, war das Hauptproblem für das spezielle Java-Beispiel nicht, dass man Closures implementieren konnte, sondern wie man sie in einer Weise in die Sprache einführte, die mit vorhandenen Features (wie anonymen inneren Klassen) und nicht redundant war das hat nicht mit vorhandenen Features gekollidiert (wie geprüften Ausnahmen - ein Problem, das nicht trivial zu lösen ist und an das die meisten Leute zuerst nicht denken).
Ich kann mir auch andere Dinge vorstellen, die die Implementierung erstklassiger Funktionen weniger trivial machen, z. B. die Entscheidung, was mit "magischen" Variablen wie dieser , self oder super zu tun ist , und die Interaktion mit vorhandenen Kontrollflussoperatoren wie break und return (Wollen wir nicht-lokale Rückgaben zulassen oder nicht?). Letztendlich scheint die jüngste Beliebtheit von erstklassigen Funktionen darauf hinzudeuten, dass Sprachen, in denen dies nicht der Fall ist, dies meist aus historischen Gründen oder aufgrund einer wichtigen Entwurfsentscheidung zu einem frühen Zeitpunkt tun.
quelle
ref
Parameter") empfängt . Wenn der Aufrufer alle relevanten Variablen in der Struktur gekapselt hat, ist der Delegat möglicherweise vollständig statisch, sodass keine Heap-Zuweisung erforderlich ist. Compiler bieten keine hilfreiche Syntaxhilfe für solche Konstrukte, aber das Framework könnte sie unterstützen.Wir können uns ansehen, wie Closures in C # implementiert sind. Der Umfang der Transformationen, die der C # -Compiler durchführt, macht deutlich, dass die Implementierung von Closures ziemlich aufwändig ist. Möglicherweise gibt es einfachere Möglichkeiten, Closures zu implementieren, aber ich denke, das C # -Compiler-Team würde sich dessen bewusst sein.
Betrachten Sie das folgende Pseudo-C # (ich habe ein bisschen C # -spezifisches Material herausgeschnitten):
Der Compiler wandelt das in so etwas um:
(In Wirklichkeit wird die Variable f weiterhin erstellt, wobei f ein 'Delegat' (= Funktionszeiger) ist, dieser Delegat jedoch weiterhin dem theClosureObject-Objekt zugeordnet ist. Ich habe diesen Teil aus Gründen der Klarheit für diejenigen weggelassen, die nicht vertraut sind mit C #)
Diese Transformation ist ziemlich umfangreich und kompliziert: Berücksichtigen Sie Closures in Closures und das Zusammenspiel von Closures mit den übrigen Funktionen der C # -Sprache. Ich kann mir vorstellen, dass das Feature für Java zurückgedrängt wurde, da Java 7 bereits viele neue Features enthält.
quelle
Um einen Teil Ihrer Frage zu beantworten. Der von Morrisett und Harper beschriebene Formalismus behandelt die Groß- und Kleinschrittsemantik polymorpher Sprachen höherer Ordnung, die Abschlüsse enthalten. Es gibt Artikel davor, die die Art der Semantik liefern, nach der Sie suchen. Schauen Sie sich zum Beispiel die SECD-Maschine an . Das Hinzufügen von veränderlichen Referenzen oder veränderlichen Einheimischen zu dieser Semantik ist unkompliziert. Ich sehe keine technischen Probleme bei der Bereitstellung einer solchen Semantik.
quelle