Nachdem ich hier viele Posts gelesen habe, in denen Schließungen erklärt werden, fehlt mir noch ein Schlüsselkonzept: Warum eine Schließung schreiben? Welche spezifische Aufgabe würde ein Programmierer ausführen, die durch einen Abschluss am besten bedient werden könnte?
Beispiele für Schließungen in Swift sind Zugriffe auf eine NSUrl und die Verwendung des Reverse Geocoders. Hier ist ein solches Beispiel. Leider präsentieren diese Kurse nur die Schließung; Sie erklären nicht, warum die Codelösung als Abschluss geschrieben ist.
Ein Beispiel für ein reales Programmierproblem, das mein Gehirn dazu veranlassen könnte, zu sagen: "Aha, ich sollte einen Abschluss dafür schreiben", wäre informativer als eine theoretische Diskussion. An theoretischen Diskussionen mangelt es auf dieser Seite nicht.
Antworten:
Erstens gibt es nichts, was ohne Verschlüsse nicht möglich wäre. Sie können einen Abschluss jederzeit durch ein Objekt ersetzen, das eine bestimmte Schnittstelle implementiert. Es ist nur eine Frage der Kürze und der reduzierten Kopplung.
Zweitens sollten Sie bedenken, dass Verschlüsse häufig unangemessen verwendet werden, wenn eine einfache Funktionsreferenz oder ein anderes Konstrukt klarer wäre. Sie sollten nicht jedes Beispiel als Best Practice betrachten.
Wo Verschlüsse wirklich über andere Konstrukte erstrahlen wird bei der Verwendung von Funktionen höherer Ordnung, wenn Sie tatsächlich benötigen Zustand zu kommunizieren, und Sie können es ein Einzeiler machen, wie in diesem JavaScript - Beispiel aus der Wikipedia - Seite über Schließungen :
Hier
threshold
wird sehr prägnant und natürlich kommuniziert, wo es definiert ist, wo es verwendet wird. Ihr Anwendungsbereich ist genau so klein wie möglich.filter
Es muss nicht geschrieben werden, um die Möglichkeit zu ermöglichen, clientdefinierte Daten wie einen Schwellenwert zu übergeben. Wir müssen keine Zwischenstrukturen definieren, um die Schwelle in dieser einen kleinen Funktion zu kommunizieren. Es ist völlig in sich geschlossen.Sie können dies ohne Abschluss schreiben, aber es wird viel mehr Code erfordern und schwieriger zu folgen sein. Außerdem hat JavaScript eine ziemlich ausführliche Lambda-Syntax. In Scala wäre zum Beispiel der gesamte Funktionskörper:
Wenn Sie jedoch ECMAScript 6 verwenden können , wird dank der Fettpfeil-Funktionen sogar der JavaScript-Code viel einfacher und kann tatsächlich in eine einzelne Zeile gesetzt werden.
Suchen Sie in Ihrem eigenen Code nach Stellen, an denen Sie viel Boilerplate generieren, um temporäre Werte von einer Stelle zur anderen zu übertragen. Dies sind hervorragende Möglichkeiten, um einen Austausch durch einen Verschluss in Betracht zu ziehen.
quelle
bestSellingBooks
Code und denfilter
Code einschränken , z. B. eine bestimmte Schnittstelle oder ein bestimmtes Benutzerdatenargument, um diethreshold
Daten kommunizieren zu können. Das verbindet die beiden Funktionen auf viel weniger wiederverwendbare Weise.Zur Erklärung leihe ich mir einen Code aus diesem hervorragenden Blog-Beitrag über Schließungen aus . Es ist JavaScript, aber das ist die Sprache, die die meisten Blog-Beiträge über Schließungen verwenden, weil Schließungen in JavaScript so wichtig sind.
Angenommen, Sie wollten ein Array als HTML-Tabelle rendern. Du könntest es so machen:
Sie sind jedoch dem JavaScript überlassen, wie jedes Element im Array gerendert wird. Wenn Sie das Rendern steuern möchten, können Sie dies tun:
Und jetzt können Sie einfach eine Funktion übergeben, die das gewünschte Rendering zurückgibt.
Was wäre, wenn Sie in jeder Tabellenzeile eine laufende Summe anzeigen möchten? Sie würden eine Variable benötigen, um diese Summe zu verfolgen, nicht wahr? Mit einem Abschluss können Sie eine Renderer-Funktion schreiben, die über der Variablen für die laufende Summe endet, und Sie können einen Renderer schreiben, der die laufende Summe verfolgt:
Die Magie, die hier geschieht, besteht darin,
renderInt
den Zugriff auf dietotal
Variable beizubehalten, auch wenn sierenderInt
wiederholt aufgerufen und beendet wird.In einer traditionelleren objektorientierten Sprache als JavaScript können Sie eine Klasse schreiben, die diese Gesamtvariable enthält, und diese weitergeben, anstatt einen Abschluss zu erstellen. Aber ein Verschluss ist eine viel mächtigere, sauberere und elegantere Art, dies zu tun.
Weitere Lektüre
quelle
Der Zweck von
closures
ist einfach, Zustand zu bewahren ; daher der Nameclosure
- es schließt sich über Zustand. Zur leichteren Erklärung verwende ich Javascript.Normalerweise haben Sie eine Funktion
Wobei der Gültigkeitsbereich der Variablen an diese Funktion gebunden ist. Nach der Ausführung verlässt die Variable den
txt
Gültigkeitsbereich. Es gibt keine Möglichkeit, darauf zuzugreifen oder sie zu verwenden, nachdem die Ausführung der Funktion abgeschlossen ist.Closures sind Sprachkonstrukte, mit denen - wie bereits gesagt - der Zustand der Variablen erhalten und damit der Geltungsbereich erweitert werden kann.
Dies kann in verschiedenen Fällen hilfreich sein. Ein Anwendungsfall ist die Konstruktion von Funktionen höherer Ordnung .
Ein einfaches, aber zugegebenermaßen nicht allzu nützliches Beispiel ist:
Sie definieren eine Funktion
makedadder
, die einen Parameter als Eingabe verwendet und eine Funktion zurückgibt . Es gibt eine äußerefunction(a){}
und eine innere Funktion.function(b){}{}
Außerdem definieren Sie (implizit) eine andere Funktionadd5
als Ergebnis des Aufrufs der Funktion höherer Ordnungmakeadder
.makeadder(5)
gibt eine anonyme ( innere ) Funktion zurück, die wiederum 1 Parameter und die Summe der Parameter der äußeren Funktion und der Parameter der inneren Funktion zurückgibt .Der Trick ist, dass bei der Rückgabe der inneren Funktion, die das eigentliche Hinzufügen vornimmt, der Gültigkeitsbereich des Parameters der äußeren Funktion (
a
) erhalten bleibt.add5
erinnert sich , dass der Parametera
war5
.Oder um ein zumindest irgendwie nützliches Beispiel zu zeigen:
Ein weiterer häufiger Anwendungsfall ist der sogenannte IIFE = sofort aufgerufene Funktionsausdruck. In Javascript ist es sehr verbreitet, private Mitgliedsvariablen zu fälschen . Dies geschieht über eine Funktion, die einen privaten Gültigkeitsbereich = erzeugt
closure
, da dieser unmittelbar nach dem Definitionsaufruf aufgerufen wird. Die Struktur istfunction(){}()
. Beachten Sie die Klammern()
nach der Definition. Dies macht es möglich, es für die Objekterstellung mit aufschlussreichem Modulmuster zu verwenden . Der Trick besteht darin, einen Bereich zu erstellen und ein Objekt zurückzugeben, das nach Ausführung des IIFE Zugriff auf diesen Bereich hat.Das Beispiel von Addi sieht so aus:
Das zurückgegebene Objekt enthält Verweise auf Funktionen (z. B.
publicSetName
), die wiederum Zugriff auf "private" Variablen habenprivateVar
.Dies sind jedoch speziellere Anwendungsfälle für Javascript.
Dafür gibt es mehrere Gründe. Man könnte sein, dass es für ihn selbstverständlich ist, da er einem funktionalen Paradigma folgt . Oder in Javascript: Es ist nur die Notwendigkeit , sich auf Verschlüsse zu verlassen, um einige Macken der Sprache zu umgehen.
quelle
Es gibt zwei Hauptanwendungsfälle für Verschlüsse:
Asynchronität. Angenommen, Sie möchten eine Aufgabe ausführen, die eine Weile dauert, und dann etwas tun, wenn sie erledigt ist. Sie können entweder Ihren Code warten lassen, bis er fertig ist, wodurch die weitere Ausführung blockiert wird und Ihr Programm möglicherweise nicht mehr reagiert, oder Sie können Ihre Aufgabe asynchron aufrufen und sagen: "Beginnen Sie diese lange Aufgabe im Hintergrund, und führen Sie diese Beendigung aus, wenn sie abgeschlossen ist." Dabei enthält der Abschluss den Code, der ausgeführt werden soll, wenn er fertig ist.
Rückrufe. Diese werden je nach Sprache und Plattform auch als "Delegates" oder "Event-Handler" bezeichnet. Die Idee ist, dass Sie ein anpassbares Objekt haben, das an bestimmten genau definierten Punkten ein Ereignis ausführt , das einen Abschluss ausführt , der von dem Code übergeben wird, der es eingerichtet hat. In der Benutzeroberfläche Ihres Programms haben Sie möglicherweise eine Schaltfläche, die den Code enthält, der ausgeführt werden soll, wenn der Benutzer auf die Schaltfläche klickt.
Es gibt mehrere andere Verwendungszwecke für Verschlüsse, aber dies sind die beiden Hauptzwecke.
quelle
Einige andere Beispiele:
Sortieren
Die meisten Sortierfunktionen arbeiten mit dem Vergleichen von Objektpaaren. Eine Vergleichstechnik ist erforderlich. Den Vergleich auf einen bestimmten Operator zu beschränken, bedeutet eine ziemlich unflexible Art. Ein viel besserer Ansatz ist es, eine Vergleichsfunktion als Argument für die Sortierfunktion zu erhalten. Manchmal funktioniert eine zustandslose Vergleichsfunktion (z. B. Sortieren einer Liste von Zahlen oder Namen), aber was ist, wenn der Vergleich den Status benötigt?
Sie können beispielsweise eine Liste der Städte nach Entfernung zu einem bestimmten Ort sortieren. Eine hässliche Lösung besteht darin, die Koordinaten dieses Ortes in einer globalen Variablen zu speichern. Dies macht die Vergleichsfunktion selbst zustandslos, jedoch auf Kosten einer globalen Variablen.
Dieser Ansatz schließt aus, dass mehrere Threads dieselbe Liste von Städten nach ihrer Entfernung zu zwei verschiedenen Standorten gleichzeitig sortieren. Ein Abschluss, der den Speicherort einschließt, löst dieses Problem und macht eine globale Variable überflüssig.
Zufallszahlen
Das Original
rand()
hat keine Argumente. Pseudozufallszahlengeneratoren benötigen einen Zustand. Einige (zB Mersenne Twister) brauchen viel Staat. Sogar der einfache, aber fürchterlichrand()
notwendige Staat. Wenn Sie ein Mathejournal über einen neuen Zufallszahlengenerator lesen, sehen Sie zwangsläufig globale Variablen. Das ist schön für die Entwickler der Technik, nicht so schön für die Anrufer. Das Einkapseln dieses Zustands in eine Struktur und die Übergabe der Struktur an den Zufallszahlengenerator ist eine Möglichkeit, das globale Datenproblem zu umgehen. Dies ist der Ansatz, der in vielen Nicht-OO-Sprachen verwendet wird, um einen Zufallszahlengenerator wiedereintrittsfähig zu machen. Eine Schließung verbirgt diesen Zustand vor dem Anrufer. Ein Closure bietet die einfache Aufrufsequenzrand()
und die Wiedereintrittsmöglichkeit des gekapselten Zustands.Zufallszahlen sind mehr als nur ein PRNG. Die meisten Leute, die Zufälligkeit wollen, wollen, dass sie auf eine bestimmte Weise verteilt wird. Ich beginne mit zufällig gezogenen Zahlen zwischen 0 und 1, oder kurz U (0,1). Jedes PRNG, das Ganzzahlen zwischen 0 und einem bestimmten Maximum generiert, ist ausreichend. Teilen Sie einfach (als Gleitkomma) die zufällige ganze Zahl durch das Maximum. Eine bequeme und allgemeine Möglichkeit, dies zu implementieren, besteht darin, einen Abschluss zu erstellen, der einen Abschluss (den PRNG) und das Maximum als Eingaben verwendet. Jetzt haben wir einen generischen und einfach zu verwendenden Zufallsgenerator für U (0,1).
Neben U (0,1) gibt es eine Reihe weiterer Verteilungen. Zum Beispiel eine Normalverteilung mit einem bestimmten Mittelwert und einer bestimmten Standardabweichung. Jeder normale Verteilungsgenerator-Algorithmus, auf den ich gestoßen bin, verwendet einen U (0,1) Generator. Eine bequeme und generische Möglichkeit, einen normalen Generator zu erstellen, besteht darin, einen Verschluss zu erstellen, der den U (0,1) -Generator, den Mittelwert und die Standardabweichung als Status enthält. Dies ist zumindest konzeptionell ein Abschluss, bei dem ein Abschluss als Argument verwendet wird.
quelle
Closures entsprechen Objekten, die eine run () -Methode implementieren, und umgekehrt können Objekte mit Closures emuliert werden.
Der Vorteil von Verschlüssen besteht darin, dass sie problemlos überall dort eingesetzt werden können, wo Sie eine Funktion erwarten: auch Funktionen höherer Ordnung, einfache Rückrufe (oder Strategiemuster). Sie müssen keine Schnittstelle / Klasse definieren, um Ad-hoc-Abschlüsse zu erstellen.
Der Vorteil von Objekten ist die Möglichkeit komplexerer Interaktionen: mehrere Methoden und / oder verschiedene Schnittstellen.
Das Verwenden von Verschlüssen oder Objekten ist also meistens eine Frage des Stils. Im Folgenden finden Sie ein Beispiel für Dinge, die das Schließen von Objekten vereinfachen, deren Implementierung jedoch unpraktisch ist:
Grundsätzlich kapseln Sie einen verborgenen Zustand, auf den nur über globale Closures zugegriffen wird: Sie müssen sich nicht auf ein Objekt beziehen, sondern verwenden nur das von den drei Funktionen definierte Protokoll.
Ich vertraue dem ersten Kommentar von supercat, dass es in einigen Sprachen möglich ist, die Lebensdauer von Objekten genau zu steuern, während dies bei Verschlüssen nicht der Fall ist. Im Fall von Sprachen mit Speicherbereinigung ist die Lebensdauer von Objekten jedoch im Allgemeinen unbegrenzt, und es ist daher möglich, einen Abschluss zu erstellen, der in einem dynamischen Kontext aufgerufen werden könnte, in dem er nicht aufgerufen werden sollte (Lesen aus einem Abschluss nach einem Stream) geschlossen ist, zum Beispiel).
Es ist jedoch recht einfach, einen solchen Missbrauch zu verhindern, indem eine Steuervariable erfasst wird, die die Ausführung eines Schließvorgangs schützt. Genauer gesagt, hier ist, was ich vorhabe (in Common Lisp):
Hier nehmen wir einen Funktionsbezeichner
function
und geben zwei Abschlüsse zurück, die beide eine lokale Variable mit dem Namen erfassenactive
:function
, nur wennactive
es wahr istaction
aufnil
, akafalse
.Stattdessen
(when active ...)
ist es natürlich möglich, einen(assert active)
Ausdruck zu haben , der eine Ausnahme auslösen kann, falls der Abschluss aufgerufen wird, wenn dies nicht der Fall sein sollte. Denken Sie auch daran, dass der unsichere Code bei unsachgemäßer Verwendung möglicherweise bereits eine Ausnahme auslöst, sodass Sie einen solchen Wrapper selten benötigen.So würden Sie es verwenden:
Beachten Sie, dass die deaktivierenden Verschlüsse auch anderen Funktionen zugewiesen werden können. Hier werden die lokalen
active
Variablen nicht zwischenf
und geteiltg
. auch, zusätzlich zuactive
,f
bezieht sich nur aufobj1
undg
nur bezieht sich aufobj2
.Der andere Punkt, den Supercat anführt, ist, dass Verschlüsse zu Speicherlecks führen können, aber leider ist dies in Umgebungen, in denen Müll gesammelt wird, für fast alles der Fall. Wenn sie verfügbar sind, kann dies durch schwache Zeiger behoben werden (der Abschluss selbst wird möglicherweise im Speicher gehalten, verhindert jedoch nicht die Speicherbereinigung anderer Ressourcen).
quelle
List<T>
Klasse in einer (hypothetischen) Klasse einschließtTemporaryMutableListWrapper<T>
und diese einem externen Code aussetzt, kann sichergestellt werden, dass der externe Code keine Möglichkeit mehr hat, den Wrapper zu manipulieren, wenn er ungültig wirdList<T>
. Man kann Verschlüsse entwerfen, um die Ungültigmachung zuzulassen, sobald sie ihren erwarteten Zweck erfüllt haben, aber es ist kaum praktisch. Es gibt Verschlüsse, um bestimmte Muster bequemer zu machen, und der Aufwand, sie zu schützen, würde dies zunichte machen.Nichts, was noch nicht gesagt wurde, aber vielleicht ein einfacheres Beispiel.
Hier ist ein JavaScript-Beispiel mit Timeouts:
Was hier passiert, ist, dass wenn
delayedLog()
aufgerufen wird, es sofort nach dem Einstellen des Timeouts zurückkehrt und das Timeout im Hintergrund weiter nach unten läuft.Wenn das Zeitlimit abgelaufen ist und die
fire()
Funktion aufgerufen wird, zeigt die Konsole diemessage
ursprünglich übergebene andelayedLog()
, da sie weiterhinfire()
über Closure verfügbar ist . Sie könnendelayedLog()
so viele Anrufe tätigen, wie Sie möchten, jedes Mal mit einer anderen Nachricht und Verzögerung, und es wird das Richtige tun.Stellen wir uns aber vor, JavaScript hat keine Closures.
Eine Möglichkeit wäre, das
setTimeout()
Blockieren - eher wie eine "Schlaf" -Funktion - so zu gestaltendelayedLog()
, dass der Gültigkeitsbereich erst nach Ablauf des Timeouts verschwindet. Aber alles zu blockieren ist nicht sehr schön.Eine andere Möglichkeit wäre, die
message
Variable in einen anderen Bereich zu verschieben, auf den zugegriffen werden kann, nachdemdelayedLog()
der Bereich verlassen wurde.Sie könnten globale - oder zumindest "umfassendere" - Variablen verwenden, aber Sie müssten herausfinden, wie Sie verfolgen können, welche Nachricht mit welchem Timeout einhergeht. Es kann jedoch nicht nur eine sequentielle FIFO-Warteschlange sein, da Sie jede gewünschte Verzögerung einstellen können. Es könnte also "first in, third out" oder so sein. Sie benötigen also ein anderes Mittel, um eine zeitgesteuerte Funktion an die benötigten Variablen zu binden.
Sie können ein Timeout-Objekt instanziieren, das den Timer mit der Nachricht "gruppiert". Der Kontext eines Objekts ist mehr oder weniger ein Bereich, der sich nicht ändert. Dann müsste der Timer im Kontext des Objekts ausgeführt werden, damit es Zugriff auf die richtige Nachricht hat. Sie müssten dieses Objekt jedoch speichern, da es ohne Verweise zu einer Müllsammlung führen würde (ohne Verschlüsse gäbe es auch keine impliziten Verweise darauf). Und Sie müssten das Objekt entfernen, sobald es abgelaufen ist, sonst bleibt es einfach hängen. Sie benötigen also eine Art Liste mit Timeout-Objekten und überprüfen diese regelmäßig auf zu entfernende "verbrauchte" Objekte. Andernfalls werden die Objekte automatisch zur Liste hinzugefügt und daraus entfernt.
Also ... ja, das wird langweilig.
Zum Glück müssen Sie keinen breiteren Bereich verwenden oder Objekte streiten, um bestimmte Variablen beizubehalten. Da JavaScript über Abschlüsse verfügt, haben Sie bereits genau den Umfang, den Sie benötigen. Ein Bereich, mit dem Sie
message
bei Bedarf auf die Variable zugreifen können. Und aus diesem Grund können Sie mit dem SchreibendelayedLog()
wie oben davonkommen .quelle
message
ist im Funktionsumfang von enthaltenfire
und wird daher in weiteren Aufrufen erwähnt; aber es tut , dass aus Versehen so zu sagen. Technisch ist es eine Schließung. +1 sowieso;)makeadder
Beispiel gesehen, das für mich ähnlich aussieht. Sie geben eine "Curry" -Funktion zurück, die ein einzelnes Argument anstelle von zwei nimmt; Mit den gleichen Mitteln erstelle ich eine Funktion, die keine Argumente akzeptiert. Ich gebe es nur nicht zurück, sondern weitersetTimeout
.message
infire
wird der Abschluss generiert. Und wenn es aufgerufensetTimeout
wird, nutzt es den konservierten Zustand.PHP kann verwendet werden, um ein reales Beispiel in einer anderen Sprache zu zeigen.
Im Grunde registriere ich eine Funktion, die für die / api / users- URI ausgeführt wird . Dies ist eigentlich eine Middleware-Funktion, die auf einem Stapel gespeichert wird. Andere Funktionen werden darum gewickelt. Ganz ähnlich wie bei Node.js / Express.js .
Der Abhängigkeitsinjektionscontainer ist (über die use-Klausel) in der Funktion verfügbar, wenn er aufgerufen wird. Es ist möglich, eine Art Routenaktionsklasse zu erstellen, aber dieser Code erweist sich als einfacher, schneller und leichter zu warten.
quelle
Ein Closure ist ein beliebiger Code, einschließlich Variablen, der als erstklassige Daten behandelt werden kann.
Ein triviales Beispiel ist guter alter Qsort: Es ist eine Funktion zum Sortieren von Daten. Sie müssen ihm einen Zeiger auf eine Funktion geben, die zwei Objekte vergleicht. Sie müssen also eine Funktion schreiben. Diese Funktion muss möglicherweise parametrisiert werden, dh, Sie geben ihr statische Variablen. Das heißt, es ist nicht threadsicher. Sie sind in DS. Sie schreiben also eine Alternative, die einen Abschluss anstelle eines Funktionszeigers akzeptiert. Sie lösen das Problem der Parametrisierung sofort, da die Parameter Teil des Abschlusses werden. Sie verbessern die Lesbarkeit Ihres Codes, indem Sie schreiben, wie Objekte direkt mit dem Code verglichen werden , der die Sortierfunktion aufruft.
Es gibt Unmengen von Situationen, in denen Sie eine Aktion ausführen möchten, die viel Code für die Kesselplatte sowie einen winzigen, aber wesentlichen Code erfordert, der angepasst werden muss. Sie vermeiden den Standardcode durch eine Funktion zu schreiben einmal , dass ein Parameter Schließung nimmt und macht die ganze vorformulierten Code um ihn herum, und dann können Sie diese Funktion aufrufen und den Code übergeben als Verschluss angepasst werden. Eine sehr kompakte und lesbare Art, Code zu schreiben.
Sie haben eine Funktion, bei der nicht-trivialer Code in vielen verschiedenen Situationen ausgeführt werden muss. Dies wurde verwendet, um entweder Code-Duplizierung oder verzerrten Code zu erzeugen, so dass der nicht-triviale Code nur einmal vorhanden war. Trivial: Sie weisen einer Variablen einen Abschluss zu und rufen ihn am besten auf, wo immer er benötigt wird.
Multithreading: iOS / MacOS X verfügt über Funktionen wie "Schließen eines Hintergrund-Threads", "... des Haupt-Threads", "... des Haupt-Threads in 10 Sekunden". Es macht Multithreading trivial .
Asynchrone Aufrufe: Das hat das OP gesehen. Jeder Anruf, der auf das Internet zugreift, oder alles andere, was Zeit in Anspruch nimmt (wie das Lesen von GPS-Koordinaten), ist etwas, auf das Sie nicht warten können. Sie haben also Funktionen, die Dinge im Hintergrund erledigen, und übergeben dann einen Abschluss, um ihnen mitzuteilen, was zu tun ist, wenn sie fertig sind.
Das ist ein kleiner Anfang. Fünf Situationen, in denen Verschlüsse revolutionär sind, wenn es darum geht, kompakten, lesbaren, zuverlässigen und effizienten Code zu erstellen.
quelle
Ein Closure ist eine Kurzform, um eine Methode dort zu schreiben, wo sie angewendet werden soll. Es erspart Ihnen den Aufwand, eine separate Methode zu deklarieren und zu schreiben. Dies ist nützlich, wenn die Methode nur einmal verwendet wird und die Methodendefinition kurz ist. Die Vorteile verringern sich bei der Eingabe, da der Name der Funktion, ihr Rückgabetyp oder ihr Zugriffsmodifikator nicht angegeben werden müssen. Außerdem müssen Sie beim Lesen des Codes nicht nach der Definition der Methode suchen.
Das Obige ist eine Zusammenfassung von Understand Lambda Expressions von Dan Avidar.
Dies hat für mich die Verwendung von Verschlüssen verdeutlicht, da es die Alternativen (Verschluss vs. Methode) und die Vorteile der einzelnen klarstellt.
Der folgende Code wird einmal und nur einmal während der Installation verwendet. Wenn Sie es unter viewDidLoad an die richtige Stelle schreiben, sparen Sie sich die Suche an anderer Stelle und verringern die Größe des Codes.
Darüber hinaus wird ein asynchroner Prozess ausgeführt, ohne dass andere Teile des Programms blockiert werden. Bei einem Abschluss bleibt ein Wert erhalten, der bei nachfolgenden Funktionsaufrufen wiederverwendet werden kann.
Ein weiterer Abschluss; Dieser erfasst einen Wert ...
quelle