Estoy leyendo el libro programming in Lua
. Dijo que
Los cierres proporcionan una herramienta valiosa en muchos contextos. Como hemos visto, son útiles como argumentos para funciones de orden superior como la ordenación. Los cierres son valiosos para funciones que también crean otras funciones, como nuestro ejemplo newCounter; Este mecanismo permite a los programas Lua incorporar técnicas sofisticadas de programación del mundo funcional. Los cierres también son útiles para las funciones de devolución de llamada. Un ejemplo típico aquí ocurre cuando crea botones en un kit de herramientas GUI convencional. Cada botón tiene una función de devolución de llamada que se llama cuando el usuario presiona el botón; desea que diferentes botones hagan cosas ligeramente diferentes cuando se presionan. Por ejemplo, una calculadora digital necesita diez botones similares, uno para cada dígito. Puede crear cada uno de ellos con una función como esta:
function digitButton (digit)
return Button{label = tostring(digit),
action = function ()
add_to_display(digit)
end}
end
Parece que si llamo al digitButton
, devolverá el action
(esto creará un cierre), por lo tanto, puedo acceder al digit
pasado digitButton
.
Mi pregunta es que:
Why we need call back functions? what situations can I apply this to?
El autor dijo:
En este ejemplo, suponemos que Button es una función del kit de herramientas que crea nuevos botones; etiqueta es la etiqueta del botón; y action es el cierre de devolución de llamada que se llamará cuando se presione el botón. La devolución de llamada se puede llamar mucho tiempo después de que digitButton realizó su tarea y después de que el dígito de la variable local se saliera del alcance, pero aún puede acceder a esta variable.
Según el autor, creo que un ejemplo similar es el siguiente:
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()
así, the callback can be called a long time after digitButton did its task and after the local variable digit went out of scope.
Respuestas:
Guy 1 a Guy 2: hola amigo, quiero hacer algo cuando un usuario hace clic allí, llámame cuando eso suceda, ¿de acuerdo?
Guy 2 devuelve la llamada Guy 1 cuando un usuario hace clic aquí.
fuente
No, nunca devolverá la acción. El botón lo ejecutará cuando el usuario haga clic en él. Y esa es la respuesta. Necesita funciones de devolución de llamada cuando desee definir acciones que deberían ocurrir en otro componente en reacción a un evento que no controla (el bucle de eventos, que es parte del sistema, ejecutará un método del botón que a su vez se ejecutará la acción).
fuente
Creo que un mejor ejemplo para el uso de devoluciones de llamada es en funciones asincrónicas. No puedo hablar por Lua, pero en JavaScript, una de las acciones asincrónicas más comunes es contactar a un servidor a través de AJAX.
La llamada AJAX es asíncrona, lo que significa que si haces algo como esto:
el contenido del
if
bloque no se ejecutará correctamente de manera confiable, y cuando lo hace, es solo porque laajaxCall()
función terminó antes de que la ejecución llegara a laif
declaración.Sin embargo, las devoluciones de llamada eliminan este problema al garantizar que la llamada asincrónica finalice antes de llamar a la función requerida. Entonces, su código cambiaría a algo como esto:
El propósito de esto es permitirle hacer cosas como recopilar datos, sin interferir con otras cosas, como dibujar la interfaz. Si la recopilación de datos fuera síncrona, la interfaz dejaría de responder mientras la aplicación esperaba obtener los datos. Una interfaz que no responde es muy mala para la experiencia del usuario, porque la mayoría de los usuarios pensarán que la aplicación se ha "bloqueado" e intentarán finalizar el proceso.
Para ver esto en acción, solo necesita mirar cualquier sitio web que realice algún tipo de actualización sin volver a cargar toda la página. Twitter, LinkedIn y los sitios de StackExchange son buenos ejemplos. El "desplazamiento sin fin" de feeds de Twitter, y las notificaciones de SE (tanto para notificaciones de usuario como para notificaciones de que una pregunta tiene nueva actividad), funcionan con llamadas asincrónicas. Cuando vea una ruleta en algún lugar, eso significa que la sección ha realizado una llamada asincrónica y está esperando que termine esa llamada, pero puede interactuar con otras cosas en la interfaz (e incluso hacer otras llamadas asincrónicas). Una vez que finalice la llamada, reaccionará y actualizará la interfaz en consecuencia.
fuente
Hiciste la pregunta
Trataré de responderlo de una manera concisa y clara (si no lo hago, consulte el enlace wiki en la parte inferior de esta respuesta).
Las devoluciones de llamada se utilizan para diferir la implementación específica de algo hasta el último momento posible.
El ejemplo del botón es una buena ilustración de esto. Supongamos que desea tener un botón en su aplicación que imprima una página en la impresora, podríamos imaginar un mundo en el que tendría que codificar una
PrinterButton
clase completamente nueva para hacer esto.Afortunadamente, tenemos la noción de devoluciones de llamada (la herencia y el uso del patrón de plantilla también es una especie de devolución de llamada semántica), por lo que no necesitamos hacer eso.
En lugar de volver a implementar cada aspecto de un botón, lo que hacemos es agregar a la implementación del botón. El
Button
tiene el concepto de hacer algo cuando se presiona. Simplemente le decimos qué es ese algo.Ese mecanismo de inyección de comportamiento en marcos se llama devoluciones de llamada.
Ejemplo:
Inyectemos un comportamiento en un botón HTML:
En este caso,
onclick
apunta a una devolución de llamada, que para este ejemplo es elprint()
método.http://en.wikipedia.org/wiki/Callback_(computer_programming)
fuente
Las funciones de devolución de llamada son muy útiles en la programación controlada por eventos. Le permiten configurar su programa de tal manera que los eventos activen el código correcto. Esto es muy común en programas con GUI donde los usuarios pueden hacer clic en cualquier elemento de la interfaz de usuario (como botones o elementos de menú) y se ejecutará el código apropiado.
fuente
Qué sucede sin devoluciones de llamada:
Chico 1: Bien, estoy esperando que eso suceda. (silbidos, pulgares torcidos)
Chico 2: ¡Maldita sea! ¿Por qué Guy 1 no me muestra cosas? ¡Quiero ver que sucedan cosas! ¿Dónde están mis cosas? ¿Cómo se supone que alguien haga algo por aquí?
fuente
En primer lugar, el término devolución de llamada se refiere a un cierre que se está utilizando para algo.
Por ejemplo, suponga que crea una función de cierre y simplemente la almacena en una variable. No es una devolución de llamada, porque no se está utilizando para nada.
Pero, suponga que crea un cierre y lo almacena en un lugar donde se llamará cuando ocurra algo. Ahora se denomina devolución de llamada.
Por lo general, las devoluciones de llamada son creadas por diferentes partes del programa que las partes que las llaman. Por lo tanto, es fácil imaginar que algunas partes del programa están "llamando" a las otras partes.
En pocas palabras, las devoluciones de llamada permiten que una parte del programa le diga a otra parte que haga algo (cualquier cosa) cuando algo sucede.
En cuanto a las variables que se mantienen vivas debido a su uso en un cierre, esa es una característica completamente diferente llamada valores ascendentes (también conocido como "extender la vida útil de las variables locales" entre aquellos que no hablan lua). Y también es bastante útil.
fuente
Extending the lifetime of local variables
también es decir el términoupvalue
.Las devoluciones de llamada han existido desde los primeros días de Fortran, al menos. Por ejemplo, si tiene un solucionador ODE (ecuación diferencial ordinaria), como un solucionador Runge-Kutta, podría verse así:
Le permite al llamante personalizar el comportamiento de la subrutina al pasarle una función de propósito especial que se llamará cuando sea necesario. Esto permite que el solucionador de ODE se use para simular una amplia variedad de sistemas.
fuente
Tropecé con esto y quise proporcionar una respuesta más actualizada ...
Las funciones de devolución de llamada nos permiten hacer algo con los datos en un momento posterior , permitiendo que se ejecute el resto de nuestro código, en lugar de esperarlo. El código asincrónico nos permite este lujo de ejecutar cualquier cosa más adelante . El ejemplo más legible de las funciones de devolución de llamada que he encontrado son Promesas en JavaScript. En el siguiente ejemplo, cada vez que ve la función (resultado) o (newResult) o (finalResult) ... estas son funciones de devolución de llamada. El código dentro de sus llaves se ejecuta una vez que los datos vuelven del servidor. Solo en este punto tendría sentido ejecutar estas funciones ya que ahora los datos que necesitan están disponibles.
el código está tomado de ... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises
Con suerte, esto ayuda a alguien. Esto es lo que ME ayudó a entender las devoluciones de llamada :)
fuente
No sé lua, pero en general los métodos de devolución de llamada son algo que le gusta el subproceso múltiple Por ejemplo, en la programación de desarrollo de aplicaciones móviles, la mayoría de las aplicaciones funcionan como enviar una solicitud al servidor y jugar con la interfaz de usuario con los datos como respuesta del servidor. Cuando el usuario envía una solicitud al servidor, llevará tiempo obtener la respuesta del servidor, pero para una mejor UX, la IU no debe bloquearse.
Debido a esto, usamos múltiples hilos para hacer operaciones paralelas. Cuando recibimos la respuesta del servidor, necesitamos actualizar la interfaz de usuario. tenemos que notificar desde ese hilo para actualizar. del mundo funcional Este tipo de llamadas a funciones se denominan métodos de devolución de llamada. Cuando llama a estos métodos, el control debería haber regresado al hilo principal. Por ejemplo, los métodos de devolución de llamada son bloques en el objetivo-C.
fuente