Ich lese das Buch programming in Lua
. Das hat es gesagt
Verschlüsse sind in vielen Zusammenhängen ein wertvolles Werkzeug. Wie wir gesehen haben, sind sie als Argumente für Funktionen höherer Ordnung wie sort nützlich. Closures sind wertvoll für Funktionen, die auch andere Funktionen erstellen, wie in unserem newCounter-Beispiel. Dieser Mechanismus ermöglicht es Lua-Programmen, ausgefeilte Programmiertechniken aus der Funktionswelt zu integrieren. Closures sind auch für Callback-Funktionen nützlich. Ein typisches Beispiel hierfür ist das Erstellen von Schaltflächen in einem herkömmlichen GUI-Toolkit. Jede Taste verfügt über eine Rückruffunktion, die aufgerufen wird, wenn der Benutzer die Taste drückt. Sie möchten, dass verschiedene Tasten beim Drücken etwas unterschiedliche Aktionen ausführen. Ein digitaler Taschenrechner benötigt beispielsweise zehn ähnliche Tasten, eine für jede Ziffer. Sie können jede davon mit einer Funktion wie der folgenden erstellen:
function digitButton (digit)
return Button{label = tostring(digit),
action = function ()
add_to_display(digit)
end}
end
Es scheint, dass, wenn ich das aufrufe digitButton
, es das zurückgibt action
(dies erzeugt einen Abschluss), so dass ich auf das digit
übergebene zugreifen kann digitButton
.
Meine Frage ist, dass:
Why we need call back functions? what situations can I apply this to?
Der Autor sagte:
In diesem Beispiel wird angenommen, dass Button eine Toolkit-Funktion ist, mit der neue Schaltflächen erstellt werden. label ist die Tastenbezeichnung; und action ist die Rückrufsperre, die beim Drücken der Taste aufgerufen wird. Der Rückruf kann lange Zeit, nachdem digitButton seine Aufgabe erfüllt hat und nachdem die Ziffer der lokalen Variablen den Gültigkeitsbereich verlassen hat, aufgerufen werden, kann jedoch weiterhin auf diese Variable zugegriffen werden.
Nach Meinung des Autors ist ein ähnliches Beispiel wie folgt:
function Button(t)
-- maybe you should set the button here
return t.action -- so that you can call this later
end
function add_to_display(digit)
print ("Display the button label: " .. tostring(digit))
end
function digitButton(digit)
return Button{label = tostring(digit),
action = function ()
add_to_display(digit)
end}
end
click_action = digitButton(10)
click_action()
somit, the callback can be called a long time after digitButton did its task and after the local variable digit went out of scope.
Antworten:
Kerl 1 bis Kerl 2: Hey Kerl, ich möchte etwas tun, wenn ein Benutzer dort einklickt, mich zurückrufen, wenn das in Ordnung ist?
Guy 2 ruft Guy 1 zurück, wenn ein Benutzer hier klickt.
quelle
Nein, es wird nie zurückkehren die Aktion. Die Schaltfläche wird ausgeführt , wenn der Benutzer darauf klickt. Und das ist die Antwort. Sie benötigen Rückruffunktionen, wenn Sie Aktionen definieren möchten, die in einer anderen Komponente als Reaktion auf ein Ereignis, das Sie nicht steuern, ausgeführt werden sollen (die Ereignisschleife, die Teil des Systems ist, führt eine Methode der Schaltfläche aus, die wiederum ausgeführt wird) die Aktion).
quelle
Ich denke, ein besseres Beispiel für die Verwendung von Rückrufen sind asynchrone Funktionen. Ich kann nicht für Lua sprechen, aber in JavaScript besteht eine der häufigsten asynchronen Aktionen darin, einen Server über AJAX zu kontaktieren.
Der AJAX-Aufruf ist asynchron, was bedeutet, dass Sie Folgendes tun:
Der Inhalt des
if
Blocks wird nicht zuverlässig korrekt ausgeführt. Wenn dies der Fall ist, wurde dieajaxCall()
Funktion nur beendet, bevor die Ausführung dieif
Anweisung erreichte.Rückrufe beseitigen dieses Problem jedoch, indem sichergestellt wird, dass der asynchrone Aufruf beendet ist, bevor die erforderliche Funktion aufgerufen wird. Ihr Code würde sich also folgendermaßen ändern:
Mit dieser Funktion können Sie beispielsweise Daten sammeln, ohne andere Dinge wie das Zeichnen der Benutzeroberfläche zu beeinträchtigen. Wenn die Datenerfassung synchron war, reagierte die Schnittstelle nicht mehr, da die Anwendung auf den Abruf der Daten wartete. Eine nicht reagierende Benutzeroberfläche ist für die Benutzererfahrung sehr schlecht, da die meisten Benutzer glauben, dass die Anwendung "abgestürzt" ist, und versuchen, den Prozess zu beenden.
Um dies in Aktion zu sehen, müssen Sie sich nur eine Website ansehen, die Aktualisierungen durchführt, ohne die gesamte Seite neu zu laden. Twitter, LinkedIn und die StackExchange-Sites sind gute Beispiele. Das "endlose Scrollen" von Feeds auf Twitter und die Benachrichtigungen von SE (sowohl für Benutzerbenachrichtigungen als auch für Benachrichtigungen, dass eine Frage neue Aktivitäten aufweist) werden durch asynchrone Aufrufe ausgelöst. Wenn Sie irgendwo ein Drehfeld sehen, bedeutet dies, dass der Abschnitt einen asynchronen Anruf getätigt hat und darauf wartet, dass dieser Anruf beendet wird. Sie können jedoch mit anderen Dingen auf der Benutzeroberfläche interagieren (und sogar andere asynchrone Anrufe tätigen). Sobald dieser Aufruf beendet ist, reagiert er und aktualisiert die Schnittstelle entsprechend.
quelle
Sie haben die Frage gestellt
Ich werde versuchen, es kurz und klar zu beantworten (falls dies nicht gelingt, lesen Sie bitte den Wiki-Link am Ende dieser Antwort).
Callbacks dienen dazu, die konkrete Umsetzung von etwas auf den letztmöglichen Moment zu verschieben.
Das Schaltflächenbeispiel veranschaulicht dies gut. Angenommen, Sie möchten eine Schaltfläche in Ihrer Anwendung haben, die eine Seite auf dem Drucker druckt. Wir könnten uns eine Welt vorstellen, in der Sie eine ganz neue
PrinterButton
Klasse codieren müssten, um dies zu tun.Glücklicherweise haben wir den Begriff der Rückrufe (Vererbung und die Verwendung des Vorlagenmusters ist auch eine Art Rückrufsemantik), so dass wir das nicht tun müssen.
Anstatt jeden Aspekt einer Schaltfläche erneut zu implementieren, müssen wir die Implementierung der Schaltfläche erweitern. Das
Button
hat das Konzept, etwas zu tun , wenn es gedrückt wird. Wir sagen einfach, was das ist.Dieser Mechanismus zum Einfügen von Verhalten in Frameworks wird als Rückruf bezeichnet.
Beispiel:
Lassen Sie uns ein bisschen Verhalten in eine HTML-Schaltfläche einfügen:
onclick
Verweist in diesem Fall auf einen Rückruf, der in diesem Beispiel dieprint()
Methode ist.http://en.wikipedia.org/wiki/Callback_(computer_programming)
quelle
Callback-Funktionen sind bei der ereignisgesteuerten Programmierung sehr nützlich. Sie ermöglichen es Ihnen, Ihr Programm so einzurichten, dass Ereignisse den richtigen Code auslösen. Dies ist sehr häufig in Programmen mit GUIs der Fall, in denen Benutzer auf ein beliebiges Element auf der Benutzeroberfläche klicken können (z. B. Schaltflächen oder Menüelemente) und der entsprechende Code ausgeführt wird.
quelle
Was passiert ohne Rückruf:
Guy 1: Okay, ich warte darauf, dass das passiert. (Pfeifen, Daumen drehen)
Typ 2: Verdammt! Warum zeigt mir Guy 1 nichts? Ich möchte sehen, was passiert !! Wo ist mein Zeug? Wie soll irgendjemand hier irgendetwas erledigen?
quelle
Zunächst einmal bezieht sich der Begriff Rückruf auf einen Abschluss, der für etwas verwendet wird.
Angenommen, Sie erstellen eine Abschlussfunktion und speichern sie einfach in einer Variablen. Es ist kein Rückruf, weil es für nichts verwendet wird.
Angenommen, Sie erstellen einen Abschluss und speichern ihn an einem Ort, an dem er aufgerufen wird, wenn etwas passiert. Es wird jetzt als Rückruf bezeichnet.
Normalerweise werden Rückrufe von anderen Programmteilen als denjenigen erstellt, die sie aufrufen. Man kann sich also leicht vorstellen, dass einige Teile des Programms die anderen Teile "zurückrufen".
Einfach ausgedrückt, erlauben Rückrufe einem Teil des Programms, einem anderen Teil anzuweisen, etwas (irgendetwas) zu tun, wenn etwas passiert.
Was die Variablen betrifft, die aufgrund der Verwendung in einem Closure am Leben bleiben, so ist dies eine völlig andere Funktion, die als Upvalues bezeichnet wird (auch bekannt als "Verlängerung der Lebensdauer lokaler Variablen" bei Personen, die kein Lua sprechen). Und es ist auch ziemlich nützlich.
quelle
Extending the lifetime of local variables
ist auch der begriff zu sagenupvalue
.Rückrufe gibt es zumindest seit den Anfängen von Fortran. Wenn Sie beispielsweise einen ODE-Löser (gewöhnlicher Differentialgleichungslöser) haben, z. B. einen Runge-Kutta-Löser, könnte dies folgendermaßen aussehen:
Es ermöglicht dem Aufrufer, das Verhalten der Unterroutine anzupassen, indem ihm eine Sonderfunktion übergeben wird, die bei Bedarf aufgerufen werden kann. Auf diese Weise kann der ODE-Solver zur Simulation einer Vielzahl von Systemen verwendet werden.
quelle
Ich bin darauf gestoßen und wollte eine aktuellere Antwort geben ...
Rückruffunktionen ermöglichen es uns, zu einem späteren Zeitpunkt etwas mit Daten zu tun , sodass der Rest unseres Codes ausgeführt werden kann, anstatt darauf zu warten. Der asynchrone Code ermöglicht uns den Luxus, etwas später auszuführen . Das am besten lesbare Beispiel für Rückruffunktionen, auf die ich gestoßen bin, sind Versprechen in JavaScript. Im folgenden Beispiel sind dies immer dann Rückruffunktionen, wenn Sie die Funktion (result) oder (newResult) oder (finalResult) sehen . Der Code in geschweiften Klammern wird ausgeführt, sobald die Daten vom Server zurückkommen. Nur zu diesem Zeitpunkt wäre es sinnvoll, diese Funktionen auszuführen, da jetzt die Daten zur Verfügung stehen, die sie benötigen.
Der Code stammt aus ... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
Hoffentlich hilft das jemandem. Dies hat mir geholfen, Rückrufe zu verstehen :)
quelle
Ich kenne lua nicht, aber im Allgemeinen Rückrufmethoden wie Multithreading. Zum Beispiel funktionieren die meisten Anwendungen in der Entwicklung mobiler Anwendungen so, als ob sie eine Anfrage an den Server senden und mit der Benutzeroberfläche spielen, wobei die Daten als Antwort vom Server kommen. Wenn der Benutzer eine Anfrage an den Server sendet, dauert es einige Zeit, bis die Antwort vom Server eingeht, aber die beste UX-Benutzeroberfläche sollte nicht hängen bleiben.
Aus diesem Grund verwenden wir mehrere Threads, um parallele Operationen durchzuführen. Wenn wir die Antwort vom Server erhalten, müssen wir die Benutzeroberfläche aktualisieren. Wir müssen von diesem Thread benachrichtigen, um zu aktualisieren. aus der funktionalen Welt. Diese Art von Funktionsaufrufen wird als Rückrufmethode bezeichnet. Wenn Sie diese Methoden aufrufen, sollte die Steuerung zum Hauptthread zurückkehren. Rückrufmethoden sind beispielsweise Blöcke in Objective-C.
quelle