viernes, 2 de diciembre de 2016

Map, filter y foldr en Erlang (funciones de alto orden)

Las funciones de alto orden son una herramienta común en la programación
funcional, con características particulares ausentes en lenguajes imperativos
tradicionales tales como Java o Python, los  cuales, no obstante, han intentado
"importar" estas funciones por lo útil y concisas que son.

Ejemplo:

2> lists:map(fun(X) -> X+2 end,lists:seq(1,10)). 
[3,4,5,6,7,8,9,10,11,12]

Explicación:
lists es un módulo estándard de Erlang, que se importa automáticamente
a su sola mención. Este método de invocar funciones dentro de bibliotecas
mediante el sufijo del módulo donde se definen se llama cualificación. Es
común en varios lenguajes (tales como Python) por su utilidad para "ocultar"
nombres de funciones que de otra manera podrían ocasionar conflictos
con algunos ya existentes o de parte del sistema o provistos por el usuario.
fun(X) -> X+2
es un ejemplo de una función lambda; el curioso nombre viene de un formalismo
básico computacional llamado cálculo lambda, el cual es un poco abstruso
pero en definitiva la base de lenguajes bien conocidos como Lisp o ML, y de
menos conocidos como Haskell o Scheme (a nivel general, no ya digamos en
México).
lists:map es una función de alto orden que reparte la aplicación de la función
de su primer argumento a cada uno de los elementos de la lista que es su
segundo argumento. Esperanzadoramente, el ejemplo ilustra bien la idea.
 Finalmente, lists:seq(1,10) crea un segmento de números naturales
representados como una lista del 1 al 10.

Ejemplo:
 3> lists:filter(fun(X) -> X<5 end, [3,4,1,7,8,9,10]).
[3,4,1]
Explicación:
lists:filter ahora toma un predicado (una función que devuelve verdadero
o falso) como primer argumento y seleccion algunos de los elementos de
una lista en su segundo argumento para "sobrevivir": solo aquellos que
satisfacen al predicado.

Ejemplo:
5> lists:foldr(fun(X,Y) -> X+Y end,0,lists:seq(1,10)).
55
Explicación:
Más complicado que los previos ejemplos, por construir.

Continuación de la explicación de foldr...
Primero, la parte fun(X,Y) -> X+Y end define una función lambda, también
llamada anónima. Las funciones lambda no tienen un nombre asignado, y
surgieron originalmente de los fundamentos del cálculo lambda (un formalismo
matemático para precisar la idea de computabilidad). La parte de 0 es la
de comienzo del operador; la parte de lists:seq(1,10) nos da una lista de 10
elementos. Matemáticamente, tendríamos que
lists:foldr(fun(X,Y) -> X+Y end,0, lists:seq(1,5))
sería la expresión
(1+(2+(3+(4+(5+0)))))
o sea, 15, y ahora se puede ver qué valor sería para la expresión dada
en 5>, previamente (sería la sumatoria desde 1 hasta 10, o sea, 55...).

Todas estas funciones más la construcción de listas compactas (ejemplo:
[X || X <- lists:seq(1,10)] ) originan una programación rápida, sin efectos
laterales, y que además se presta a tratamiento algebraico. Por ejemplo,
map (f (map g lista))= map (f o g) lista
evitando un doble recorrido en la lista, en donde f o g es la función
compuesta de f y g.

1 comentario:

  1. las funciones Map, filter y no son muy difíciles de entender. Sin embargo por lo que entiendo de la función foldr es como un tipo de recursividad lineal con un valor inicial dado por el segundo parametro y los valores a recorrer recursivamente son los dados por el tercer parametro

    ResponderEliminar