Retrollamada (informática)
De Wikipedia, la enciclopedia libre
De Wikipedia, la enciclopedia libre
En programación informática, una retrollamada o devolución de llamada (en inglés: callback)[1] es una función ejecutable «A» que se usa como argumento de otra función «B». De esta forma, al llamar a «B», esta ejecutará «A». Esta acción puede ser inmediata, lo que se denominará retrollamada sincronizada o puede producirse en un punto posterior, lo que se denominaría retrollamada asíncrona. Los lenguajes de programación son compatibles con distintos tipos de retrollamadas, en ocasiones implementándolas con subrutinas, expresiones lambda o bloques de código.
Esto permite desarrollar capas de abstracción de código genérico a bajo nivel que pueden ser llamadas desde una subrutina (o función) definida en una capa de mayor nivel. Por lo general, el código de alto nivel empieza con la llamada de alguna función, definida a bajo nivel, pasando a esta un puntero o un puntero inteligente de alguna otra función. Mientras la función de bajo nivel se ejecuta, esta puede ejecutar a su vez la función pasada como puntero para realizar alguna tarea. En otro escenario, las funciones de bajo nivel registran otras funciones pasadas como puntero inteligente, que luego pueden ser utilizadas para realizar retrollamadas asíncronas.
Se puede utilizar una retrollamada como aproximación simple al polimorfismo y a la programación genérica, donde el comportamiento de una función puede ser determinado dinámicamente por el paso punteros o punteros inteligentes a funciones de bajo nivel en las que, aunque realicen tareas diferentes, los argumentos sean compatibles entre sí. A esta técnica se le conoce como reutilización de código.
Estas funciones de retrollamadas tienen una gran variedad de usos. Por ejemplo, podría ser una función que lee un archivo de configuración y que asocia valores con opciones. Si las opciones están identificadas con un hash, entonces se escribe la función tal que haga una retrollamada, haciéndolo lo hace más flexible: su usuario puede elegir qué algoritmo de hash desea y la función continuará trabajando, ya que usa la retrollamada para cambiar los nombres de las opciones en los hashes; así, las retrollamadas permiten al usuario de una función personalizarla durante su ejecución.
Se puede considerar como ejemplo el problema de realizar varias operaciones arbitrarias en una lista. Una opción puede ser iterar sobre la lista, o también realizar alguna operación sobre cada uno de los elementos de la lista. En la práctica, la solución más común, pero no ideal, es utilizar iteradores (como un bucle for
) que deberán duplicarse en cada lugar del código donde sea necesario. Más aún, si la lista es actualizada por un proceso asíncrono (por ejemplo, si un elemento es añadido o eliminado), en el iterador podría corromperse durante su paso a través de la lista.
Una alternativa podría ser crear una nueva biblioteca de funciones que ejecute la tarea deseada con la sincronización apropiada en cada caso. Esta propuesta aún requiere que cada nueva función de la biblioteca contenga el código para ir a través de la lista. Esta solución no es aceptable para bibliotecas genéricas que tengan como objetivo varias aplicaciones; el desarrollador de la biblioteca no puede anticiparse a las necesidades de cada aplicación y el desarrollador de las aplicaciones no debería necesitar conocer los detalles de la implementación de la biblioteca.
En este caso las retrollamadas resuelven estos problemas. Un procedimiento es escribir el paso a través de una lista que provee a la aplicación del código para ir a través de la lista, operando sobre cada elemento. Existe una clara distinción entre la biblioteca y la aplicación sin sacrificar la flexibilidad. Una retrollamada también se puede considerar un tipo de rutina enlazada por referencia.
Otro uso es en la señalización de errores. Un programa en un sistema operativo Unix, por ejemplo, podría no querer terminar inmediatamente cuando recibe un SIGTERM; para tomar los recaudos necesarios, una función de retrollamada podría efectuar una limpieza.
También puede utilizarse para controlar si una función actúa o no: Xlib permite predicados personalizables a especificarse para determinar si un programa desea manipular un evento.
La forma de una retrollamada varía según el lenguaje de programación:
El siguiente código en C demuestra el uso de funciones de retrollamada para mostrar dos números:
#include <stdio.h>
#include <stdlib.h>
/* La función de llamada toma una simple retrollamada como un parámetro. */
void ImprimirDosNumeros(int (*numeroEntrada)(void)) {
printf("%d y %d\n", numeroEntrada(), numeroEntrada());
}
/* Una posible retrollamada. */
int unaRetrollamada(void) {
return (rand() % 1000) + 9001;
}
/* Otra posible retrollamada. */
int otraRetrollamada(void) {
return 42;
}
/* El programa principal llama a ImprimrDosNumeros() con tres retrollamadas diferentes. */
int main(void) {
ImprimirDosNumeros(&rand);
ImprimirDosNumeros(&unaRetrollamada);
ImprimirDosNumeros(&otraRetrollamada);
return 0;
}
Este ejemplo daría una salida en consola similar a:
125185 y 89188225 9084 y 9441 42 y 42
Las retrollamadas se usan para la implementación de lenguajes como JavaScript, incluyendo el soporte de funciones JavaScript y retrollamadas mediante js-ctypes y en componentes como addEventListener.[6] Sin embargo, un ejemplo nativo de una retrollamada puede escribirse sin ningún código complejo:
function calculate(num1, num2, callbackFunction) {
return callbackFunction(num1, num2);
}
function calcProduct(num1, num2) {
return num1 * num2;
}
function calcSum(num1, num2) {
return num1 + num2;
}
// alerta a 75, producto de 5 y 15
alert(calculate(5, 15, calcProduct));
// alerta a 20, la suma de 5 y 15
alert(calculate(5, 15, calcSum));
Ejemplo de colores con el motor de Roblox con una retrollamada .done opcional:
wait(1)
local DT = wait()
function tween_color(object, finish_color, fade_time)
local step_r = finish_color.r - object.BackgroundColor3.r
local step_g = finish_color.g - object.BackgroundColor3.g
local step_b = finish_color.b - object.BackgroundColor3.b
local total_steps = 1/(DT*(1/fade_time))
local completed;
coroutine.wrap(function()
for i = 0, 1, DT*(1 / fade_time) do
object.BackgroundColor3 = Color3.new (
object.BackgroundColor3.r + (step_r/total_steps),
object.BackgroundColor3.g + (step_g/total_steps),
object.BackgroundColor3.b + (step_b/total_steps)
)
wait()
end
if completed then
completed()
end
end)()
return {
done = function(callback)
completed = callback
end
}
end
tween_color(some_object, Color3.new(1, 0, 0), 1).done(function()
print "Color tweening finished!"
end)
Un uso clásico de las retrollamadas en Python (y otros lenguajes de programación) es asignar eventos a elementos de la interfaz.
Aquí hay un pequeño ejemplo del uso de una retrollamada en Python. Primero define dos funciones, la retrollamada y el código de llamada. Después pasa la función de retrollamada al código de llamada.
>>> def get_square(val):
... """La retrollamada."""
... return val ** 2
...
>>> def caller(func, val):
... return func(val)
...
>>> caller(get_square, 5)
25
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.