programacion-referencias-a-funciones

Qué son y cómo usar las referencias a funciones

Una REFERENCIA a función es un tipo de dato que, en lugar de tener simplemente datos, contiene un enlace a una función específica en memoria.

Al principio puede sorprender el concepto, porque cuando empiezas a programar te acostumbras a tener variables con datos por un lado, y funciones que las manipulan por otras.

Pero cuando hablamos de variables, dijimos que una variable es “una caja” que podía contener diferentes cosas. O como diría Peter Griffin… “una caja puede tener cualquier cosa… ¡hasta un barco!”

Ahora, esto incluye contener funciones, no solo datos.

referencia-funciones

Una variable que contiene una función

¿Qué ventajas tiene poder asignar la función a una variable? Que ahora podemos tratar una función como un objeto que se puede asignar, pasar como argumento, devolver como resultado o almacenar en una estructura de datos.

No te preocupes si “te cuesta pillarle el truquillo”. Pero es una técnica muy potente que nos permite separar la implementación de la función de su alias para invocarlo llamada, lo que facilita la reutilización del código y la creación de código modular.

Referencia a funciones

Vamos a traducir lo que hemos dicho a algo de código (no te preocupes mucho por la sintaxis, luego vemos ejemplos concretos. Ahora solo es una excusa para entendernos).

Lo que decía es que normalmente estamos acostumbrados a tener,

  • Variables que contienen datos como mi_variable que contiene 10
  • Funciones, como DoSomething, que realizan acciones

Es decir, algo así,

// una variable con datos
const mi_variable = 10

// una funcion
function DoSomething()
{
}

DoSomething() // invocar a la función

Ahora vamos a ver como combinar ambas cosas, una variable que contiene una REFERENCIA a la función. En este caso, quedaría algo así,

// una funcion
function DoSomething()
{
}

// una variable que contiene una funcion
const mi_variable = doSomething;

mi_variable() // invocar a una funcion a traves de la variable

En lugar de llamar a la función por su nombre original, podemos utilizar nuestra REFERENCIA a la función para invocarla.

Importante, hay que tener cuidado y diferenciar entre asignar e invocar a la función. Por ejemplo, en el siguiente caso, observar la diferencia entre asignar la función e invocar la función.

// esto asigna la funcion a la variable
var mi_variable = doSomething;

// esto invoca la funcion y asigna el resultado a la variable
var mi_variable = doSomething();

La forma de invocar a la función dependerá del lenguaje que estemos usando. En general es (). Pero en cualquier caso los conceptos son los mismos. A continuación vemos casos concretos de implementación en lenguajes.

Ejemplos de referencias a funciones en distintos lenguajes

Vamos a ver un ejemplo de cómo hacer una referencia a una función en distintos lenguajes. Para el ejemplo, vamos a crear una función suma que admite dos parámetros a y b y devuelva la suma.

Luego crearemos una variable funcion_suma que contenga una referencia a la función. Luego invocamos esta función a través de la variable, en lugar de a partir de su nombre.

Así quedaría este ejemplo en distintos lenguajes de programación.

C# tiene el concepto de delegado, que es un sistema de Referencias de Funciones.

// Definición de la función suma
int Suma(int a, int b)
{
	return a + b;
}

void Main(string[] args)
{
	// Asignación de la función a un delegado
	Func<int, int, int> funcion_suma = Suma;

	// Invocación de la función a través del delegado
	Console.WriteLine(funcion_suma(3, 4)); // Imprime: 7
}

En C++ existe el concepto de puntero, que permite establecer Referencias a Funciones.

// Definición de la función suma
int suma(int a, int b) {
    return a + b;
}

int main() {
    // Asignación de la función a un puntero a función
    int (*funcion_suma)(int, int) = suma;

    // Invocación de la función a través del puntero
    std::cout << funcion_suma(3, 4) << std::endl; // Imprime: 7
}

JavaScript es un lenguaje de tipado dinámico. Por supuesto, es posible usar las variables para contener a otras funciones. De hecho, es muy frecuente en este lenguaje.

// Definición de la función suma
function suma(a, b) {
    return a + b;
}

// Asignación de la función a una variable
const funcion_suma = suma;

// Invocación de la función a través de la variable
console.log(funcion_suma(3, 4)); // Imprime: 7

Finalmente Python también es compatible con Referencias a funciones. En este caso, ni siquiera es necesario declarar la variable, simplemente asignar la función.

# Definición de la función suma
def suma(a, b):
    return a + b

# Asignación de la función a una variable
funcion_suma = suma

# Invocación de la función a través de la variable
print(funcion_suma(3, 4)) # Imprime: 7

Como vemos, aparte de las diferencias de sintaxis, los conceptos e incluso el uso son básicamente idénticos.

Funcionamiento interno Avanzado

El funcionamiento de las referencias a funciones está implementado de diferentes formas según el lenguaje de programación. Sin embargo, a grandes rasgos, podemos dar una explicación común de cómo funcionan.

Cuando una función es definida en un lenguaje de programación, su código es almacenado en una ubicación específica de memoria. Esta ubicación es identificada por una dirección de memoria única.

Una referencia a función es simplemente un tipo de dato que contiene esta dirección de memoria. Cuando pasamos una función como referencia a otra función o la almacenamos en una variable, lo que realmente estamos haciendo es almacenar esta dirección de memoria.

referencia-funcion-interno

Cuando utilizamos una referencia a función para invocar a la función referenciada, el programa accede a la dirección de memoria almacenada en la referencia y ejecuta el código almacenado en esa ubicación.

Además, esto permite que el programa invoque dinámicamente la función referenciada en tiempo de ejecución, lo que brinda flexibilidad y dinamismo al código.

En realidad, si lo pensáis no deja de ser un GO-TO. Pero hiper vitaminado, y mucho más controlado y seguro.