Je lis le livre programming in Lua
. Il a dit que
Les fermetures constituent un outil précieux dans de nombreux contextes. Comme nous l'avons vu, ils sont utiles comme arguments pour des fonctions d'ordre supérieur telles que le tri. Les fermetures sont précieuses pour les fonctions qui construisent également d'autres fonctions, comme notre exemple newCounter; ce mécanisme permet aux programmes Lua d'incorporer des techniques de programmation sophistiquées du monde fonctionnel. Les fermetures sont également utiles pour les fonctions de rappel. Un exemple typique se produit ici lorsque vous créez des boutons dans une boîte à outils GUI conventionnelle. Chaque bouton a une fonction de rappel à appeler lorsque l'utilisateur appuie sur le bouton; vous voulez que différents boutons fassent des choses légèrement différentes lorsqu'ils sont pressés. Par exemple, une calculatrice numérique a besoin de dix boutons similaires, un pour chaque chiffre. Vous pouvez créer chacun d'eux avec une fonction comme celle-ci:
function digitButton (digit)
return Button{label = tostring(digit),
action = function ()
add_to_display(digit)
end}
end
Il semble que si j'appelle le digitButton
, il retournera le action
(cela créera une fermeture), donc je peux accéder au digit
passé digitButton
.
Ma question est la suivante:
Why we need call back functions? what situations can I apply this to?
L'auteur a dit:
Dans cet exemple, nous supposons que Button est une fonction de boîte à outils qui crée de nouveaux boutons; label est l'étiquette du bouton; et action est la fermeture de rappel à appeler lorsque le bouton est enfoncé. Le rappel peut être appelé longtemps après que digitButton a fait sa tâche et après que la variable locale digit soit hors de portée, mais il peut toujours accéder à cette variable.
selon l'auteur, je pense qu'un exemple similaire ressemble à ceci:
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()
Donc, the callback can be called a long time after digitButton did its task and after the local variable digit went out of scope.
Réponses:
Guy 1 à Guy 2: hé mec, je veux faire quelque chose quand un utilisateur clique dessus, rappelez-moi quand ça se passe bien?
Guy 2 rappelle Guy 1 lorsqu'un utilisateur clique ici.
la source
Non, il ne retournera jamais l'action. Le bouton l' exécutera lorsque l'utilisateur cliquera dessus. Et voilà la réponse. Vous avez besoin de fonctions de rappel lorsque vous souhaitez définir des actions qui doivent se produire dans un autre composant en réaction à un événement que vous ne contrôlez pas (la boucle d'événements, qui fait partie du système, exécutera une méthode du bouton qui à son tour s'exécutera l'action).
la source
Je pense qu'un meilleur exemple pour l'utilisation des rappels est dans les fonctions asynchrones. Je ne peux pas parler pour Lua, mais en JavaScript, l'une des actions asynchrones les plus courantes consiste à contacter un serveur via AJAX.
L'appel AJAX est asynchrone, ce qui signifie que si vous faites quelque chose comme ceci:
le contenu du
if
bloc ne fonctionnera pas correctement de manière fiable, et quand il le fera, c'est uniquement parce que laajaxCall()
fonction s'est terminée avant que l'exécution n'atteigne l'if
instruction.Cependant, les rappels éliminent ce problème en garantissant que l'appel asynchrone est terminé avant d'appeler la fonction requise. Ainsi, votre code se changerait en quelque chose comme ceci:
Le but de ceci est de vous permettre de faire des choses comme collecter des données, sans interférer avec d'autres choses, comme dessiner l'interface. Si la collecte de données était synchrone, l'interface ne répondrait plus pendant que l'application attendait d'obtenir les données. Une interface qui ne répond pas est très mauvaise pour l'expérience utilisateur, car la plupart des utilisateurs penseront que l'application a "planté" et essaieront de terminer le processus.
Pour voir cela en action, il vous suffit de consulter n'importe quel site Web qui effectue n'importe quel type de mise à jour sans recharger la page entière. Twitter, LinkedIn et les sites StackExchange en sont de bons exemples. Le "défilement sans fin" des flux de Twitter et les notifications de SE (pour les notifications des utilisateurs et les notifications qu'une question a une nouvelle activité) sont alimentés par des appels asynchrones. Lorsque vous voyez un spinner quelque part, cela signifie que la section a effectué un appel asynchrone et attend que cet appel se termine, mais vous pouvez interagir avec d'autres choses sur l'interface (et même effectuer d'autres appels asynchrones). Une fois cet appel terminé, il réagira et mettra à jour l'interface en conséquence.
la source
Vous avez posé la question
J'essaierai d'y répondre de manière concise et claire (si j'échoue à cela, veuillez vous référer au lien wiki au bas de cette réponse).
Les rappels sont utilisés pour reporter l'implémentation spécifique de quelque chose au dernier moment possible.
L'exemple de bouton en est une bonne illustration. Supposons que vous vouliez avoir un bouton dans votre application qui imprime une page sur l'imprimante, nous pourrions imaginer un monde où vous auriez à coder un tout nouveau
PrinterButton
classe pour ce faire.Heureusement, nous avons la notion de callbacks (héritage et utilisation du modèle de modèle est également une sorte de sémantique de rappel), nous n'avons donc pas besoin de le faire.
Au lieu de réimplémenter chaque aspect d'un bouton, ce que nous faisons est d'ajouter à l'implémentation du bouton. Le
Button
a le concept de faire quelque chose quand il est pressé. Nous lui disons simplement ce qu'est ce quelque chose.Ce mécanisme d'injection de comportement dans les frameworks est appelé callbacks.
Exemple:
Injectons un certain comportement dans un bouton HTML:
Dans ce cas,
onclick
pointe vers un rappel, qui pour cet exemple est laprint()
méthode.http://en.wikipedia.org/wiki/Callback_(computer_programming)
la source
Les fonctions de rappel sont très utiles dans la programmation événementielle. Ils vous permettent de configurer votre programme de telle manière que les événements déclenchent le code correct. Ceci est très fréquent dans les programmes avec GUI où les utilisateurs peuvent cliquer sur n'importe quel élément de l'interface utilisateur (tels que les boutons ou les éléments de menu) et le code approprié sera exécuté.
la source
Que se passe-t-il sans rappels:
Guy 1: D'accord, j'attends que cette chose arrive. (sifflets, pouces twiddles)
Guy 2: Bon sang! Pourquoi Guy 1 ne me montre-t-il pas des trucs? Je veux voir des choses se passer !! Où est mon équipement? Comment peut-on faire quoi que ce soit ici?
la source
Tout d'abord, le terme rappel fait référence à une fermeture qui est utilisée pour quelque chose.
Par exemple, supposons que vous créez une fonction de fermeture et que vous la stockiez simplement dans une variable. Ce n'est pas un rappel, car il n'est utilisé pour rien.
Mais supposons que vous créiez une fermeture et la stockiez quelque part où elle sera appelée quand quelque chose se passera. Il est maintenant appelé un rappel.
Habituellement, les rappels sont créés par différentes parties du programme que les parties qui les appellent. Il est donc facile d'imaginer que certaines parties du programme "rappellent" les autres parties.
Autrement dit, les rappels permettent à une partie du programme de dire à une autre partie de faire quelque chose (n'importe quoi) quand quelque chose se produit.
Quant aux variables maintenues en vie en raison de leur utilisation dans une fermeture, c'est une fonctionnalité complètement différente appelée upvalues (alias "prolonger la durée de vie des variables locales" parmi ceux qui ne parlent pas Lua). Et c'est aussi très utile.
la source
Extending the lifetime of local variables
c'est aussi dire le termeupvalue
.Les rappels existent depuis les premiers jours de Fortran, au moins. Par exemple, si vous avez un solveur ODE (équation différentielle ordinaire), tel qu'un solveur Runge-Kutta, il pourrait ressembler à ceci:
Il permet à l'appelant de personnaliser le comportement du sous-programme en lui transmettant une fonction spéciale à appeler si nécessaire. Cela permet au solveur ODE d'être utilisé pour simuler une grande variété de systèmes.
la source
Je suis tombé sur cela et je voulais apporter une réponse plus à jour ...
Les fonctions de rappel nous permettent de faire quelque chose avec les données ultérieurement , permettant au reste de notre code de s'exécuter, au lieu de l'attendre. Le code asynchrone nous permet ce luxe d'exécuter quoi que ce soit plus tard . L'exemple le plus lisible de fonctions de rappel que j'ai rencontré est Promises in JavaScript. Dans l'exemple ci-dessous chaque fois que vous voyez la fonction (résultat) ou (nouveauRésultat) ou (finalRésultat) ... ce sont des fonctions de rappel. Le code entre crochets est exécuté une fois que les données reviennent du serveur. Ce n'est qu'à ce stade qu'il serait judicieux d'exécuter ces fonctions puisque maintenant les données dont elles ont besoin sont disponibles.
le code est extrait de ... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
Espérons que cela aide quelqu'un. C'est ce qui m'a aidé à comprendre les rappels :)
la source
Je ne connais pas lua mais dans les méthodes de rappel générales, certains aiment le multithreading. Par exemple, dans la programmation de développement d'applications mobiles, la plupart des applications fonctionnent comme l'envoi de requêtes au serveur et le jeu avec l'interface utilisateur avec les données fournies par le serveur. Lorsque l'utilisateur envoie une demande au serveur, il faudra du temps pour obtenir une réponse du serveur, mais pour le meilleur UX UI ne doit pas rester bloqué.
Pour cette raison, nous utilisons plusieurs threads pour effectuer des opérations parallèles. Lorsque nous recevons la réponse du serveur, nous devons mettre à jour l'interface utilisateur. nous devons informer de ce fil pour mettre à jour. du monde fonctionnel. Ce type d'appels de fonction est appelé méthode de rappel. Lorsque vous appelez ces méthodes, le contrôle doit avoir retourné au thread principal. Par exemple, les méthodes de rappel sont des blocs de l'objectif-C.
la source