Bienvenidos sean a este post, en Lua las funciones son valores de primera clase rango lexico apropiado pero que significa valor de primera clase? Esto significa que una funcion es un valor con los mismos derechos que los valores convencionales como numeros y cadenas, en casos anteriores vimos como las funciones pueden ser almacenadas en variables y en tablas, pueden ser pasadas por argumentos y pueden ser devueltas por otras funciones pero que significa rango lexico apropiado? Esto significa que las funciones pueden acceder a variables de sus funciones de cierre, esta aparente propiedad inocua le concede un gran poder a este lenguaje porque esto nos permite aplicar muchas tecnicas de programacion poderosas, inclusive si no estas tan interesado en programacion funcional igualmente vale la pena aprender un poco como explorar estas tecnicas porque podemos lograr un programa mas chico y mas simple.

Anuncios

En LUA una nocion que confunde es que las funciones, como todos los otros valores, son anonimos y ellos no poseen nombres porque cuando hablamos sobre el nombre de una funcion, por ejemplo como print, en realidad estamos hablando sobre una variable que contiene a esa funcion y tal como otras variables que contienen valores nosotros podemos manipularlas de muchas maneras, veamos los siguientes ejemplos:

tinchicus@dbn001dsk:~/lenguaje/lua$ lua5.3
Lua 5.3.3  Copyright (C) 1994-2016 Lua.org, PUC-Rio
> a = { p=print }
> a.p("Hola, Mundo")
Hola, Mundo
> print = math.sin
> a.p(print(1))
0.8414709848079
> sin = a.p
> sin(10, 20)
10      20
>

Primero usaremos una tabla llamada a donde tendra una posicion p la cual almacenara a print, en nuestro segundo caso usamos la tabla a con la posicion p y le pasamos un literal, observen como al presionar Enter nos muestra el literal que informamos, en el siguiente caso reemplazamos a print por math.sin, la siguiente linea equivaldria a hacer esto:

print(math.sin(1))

Por eso al darle Enter obtendremos el resultado de la operacion seno del valor 1, para nuestro ultimo caso reemplazamos a sin con el valor de a.p, al utilizarlo nos mostrara los valores como si hubiera sido print(10, 20).

Anuncios

Por lo visto hasta ahora si las funciones son valores, hay expresiones que crean funciones? Si, de hecho la forma mas usual de escribir una funcion en Lua es:

function foo(x) return 2*x end 

Esto es una simple instancia de lo que llamamos “azucar sintactico”, lo que significa que es una forma bonita de escribir el siguiente codigo:

foo = function (x) return 2*x end

Por lo tanto podemos decir que una definicion de una funcion es una declaracion que crea un valor de tipo “funcion” y asignarselo a una variable, como podemos ver la expresion:

function (x) body end 

Como un constructor de funcion, asi como {} es un constructor de tabla, cada resultado de dichas constructores de funciones lo llamamos funciones anonimas, y a menudo asignamos esas funciones a variables globales dandole un nombre pero hay muchas ocasiones que las funciones permanecen anonimas.

La libreria table provee una funcion llamada table.sort la cual recibe los elementos y los ordena, como una funcion debe permitir ilimitadas variaciones a la hora de ordenar los elementos:

  • Ascendente
  • Descendente
  • Numerico
  • Alfabetico
  • Tablas ordenadas por una clave
  • etc…
Anuncios

En lugar de intentar proveer toda especies de opciones, sort provee un solo parametro opcional llamado funcion de orden: la cual recibe dos elementos y devuelve cual debe ser el primero en venir antes del segundo en la lista ordenada, vamos a suponer la siguiente tabla:

redes = {
	{nombre = "grauna", IP = "210.26.30.34"},
	{nombre = "arraial", IP = "210.26.30.23"},
	{nombre = "lua", IP = "210.26.23.12"},
	{nombre = "derain", IP = "210.26.23.20"}
}

Si quisieramos ordenar la tabla por nombre y de forma alfabetica descendiente, debemos usar lo siguiente:

table.sort(redes, function(a,b) return (a.nombre > b.nombre) end)

En este caso podemos ver como manejamos una funcion anonima en esta declaracion, si desean probarlo se vera de la siguiente forma:

tinchicus@dbn001dsk:~/lenguaje/lua$ lua5.3
Lua 5.3.3  Copyright (C) 1994-2016 Lua.org, PUC-Rio
> redes = {
>> {nombre = "grauna", IP = "210.26.30.34"},
>> {nombre = "arraisi", IP = "210.26.30.23"},
>> {nombre = "lua", IP = "210.26.23.12"},
>> {nombre = "derain", IP = "210.26.23.20"}
>> }
> table.sort(redes, function(a,b) return (a.nombre > b.nombre) end)
> for i=1, #redes do
>> print(redes[i].nombre)
>> end
lua
grauna
derain
arraisi
>

Observen como al usar un for para mostrar el contenido de redes este se encuentra en el orden que hicimos mediante la funcion table.sort, este mecanismo que usamos en table.sort, es decir usar una funcion como argumento de otra funcion es llamado funcion de orden superior.

Anuncios

Las funciones de orden superior son un mecanismo poderoso de programacion y el uso de funciones anonimas para crear argumentos de una funcion son una gran fuente de flexibilidad pero recuerden que estos mecanismos no poseen permisos especiales y son una consecuencia directa de la habilidad de Lua para manejar funciones como valores de primera clase, para entender mejor el concepto de funciones de orden superior vamos a hacer una funcion para calcular la derivada, para ello implementaremos la siguiente funcion:

function derivada(f, delta)
	delta = delta or 1e-4
	return function(x)
			return (f(x - delta) -f(x))/delta
		end
end

Esta funcion recibira dos valores (f y delta), luego le asignaremos a delta el valor informado o sino por medio de or le asignara el valor 1e-4, despues devolveremos el valor de una funcion anonima la cual hara el calculo de la derivada (un calculo aproximado no es la formula exacta), para poder probar su uso podemos hacerlo de la siguiente forma:

c = derivada(math.sin)
print(math.cos(10), c(10))

En este caso asignaremos a c la funcion derivada y en este caso a f le asignaremos el valor de math.sin, la siguiente linea nos mostrara el valor de coseno de 10 y por ultimo a c le pasaremos el valor de 10 que sera asignado a delta, a continuacion lo probaremos en modo interactivo para ver su salida:

tinchicus@dbn001dsk:~/lenguaje/lua$ lua5.3
Lua 5.3.3  Copyright (C) 1994-2016 Lua.org, PUC-Rio
> function derivada(f, delta)
>> delta = delta or 1e-4
>> return function(x)
>> return (f(x + delta) - f(x))/delta
>> end
>> end
> c = derivada(math.sin)
> print(math.cos(10), c(10))
-0.83907152907645       -0.83904432662041
>

En este caso podemos ver como al mostrar los dos resultados son iguales, y aca tambien podemos ver otra particularidad, como dijimos antes, las funciones al ser valores de primera clase podremos almacenarlas en variables tanto globales como locales e inclusive tablas pero ese sera un tema que veremos mas adelante.

Anuncios

En resumen, hoy hemos hablado sobre conductas particulares de las funciones, que tipo son, como implementarlas, hemos hablado de funciones anonimas y tambien como implementar funciones de orden superior, espero les haya sido util sigueme en Twitter o Facebook para recibir una notificacion cada vez que subo un nuevo post en este blog, nos vemos en el proximo post.

Tambien podes donar

Es para mantenimiento del sitio, gracias!

$1.00