Map, Filter y Reduce en Python (porque no solo Lisp tiene alto orden)
Estas son las funciones "paradigmáticas" de alto orden. Se las llama así porque toman como parámetro una función, para lo cual es necesario que las funciones sean objetos de primer orden en el lenguaje.
Map aplica la función a todos los elementos de la lista.
Filter crea una nueva lista con los elementos para los cuales evaluar la función da verdadero.
Reduce es menos intuitivo

Ahora se va a ver.
Código:
>>> numeros = range(10)
>>> numeros
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> def esPar(x): return x % 2 == 0
...
>>> def alCuadrado(x): return x ** 2
...
>>> def suma(a,b): return a + b
...
>>> alCuadrado
<function alCuadrado at 0xb7d24374>
>>> esPar
<function esPar at 0xb7d2433c>
Las versiones funcionales en Python tienen también sus versiones de "lista por comprensión", que suelen ser más intuitivas y lindas de usar.
Código:
>>> map(alCuadrado, numeros)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> [alCuadrado(x) for x in numeros]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> filter(esPar, numeros)
[0, 2, 4, 6, 8]
>>> [x for x in numeros if esPar(x)]
[0, 2, 4, 6, 8]
>>> filter(esPar, map(alCuadrado, numeros))
[0, 4, 16, 36, 64]
>>> [x for x in [alCuadrado(n) for n in numeros] if esPar(x)]
[0, 4, 16, 36, 64]
>>> reduce(suma, numeros)
45
>>> buf = 0
>>> for n in numeros:
... buf += n
...
>>> buf
45
Lo bueno de que las funciones "mapeadas" o "filtradas" no tengan efectos secundarios (o sea, no hagan nada más que crear la lista que devuelven) es que paralelizar es una pavada, como decía gera - al hacer map de una función si se tiene más de un procesador se puede ejecutar la función en paralelo.
En el caso de reduce es menos trivial, la ejecución en paralelo "obvia" solo funciona cuando la función que se aplica es asociativa (o sea f(f(a,b),c) = f(a, f(b,c)), como es el caso con la suma o el producto). Esto no siempre ocurre, pero cuando es así se puede dividir la lista a reducir a varias partes y al terminar de reducir cada una, crear una nueva lista con los nuevos valores y reducir cada mitad.
Código:
>>> def resta(x,y): return x-y # La resta no es asociativa!
...
>>> num1 = numeros[:5]
>>> num1
[0, 1, 2, 3, 4]
>>> num2 = numeros[5:]
>>> num2
[5, 6, 7, 8, 9]
>>> num1 + num2 == numeros
True
>>> reducidos = [reduce(suma, num1) , reduce(suma, num2)]
>>> reduce(suma, reducidos)
45
>>> reduce(suma, numeros) # Da lo mismo!
45
>>> reducidos = [reduce(resta, num1), reduce(resta, num2)]
>>> reduce(resta, reducidos)
15
>>> reduce(resta, numeros)
-45
Más allá de la elegancia, las versiones por comprensión son más expresivas que map y filter. Reduce no tiene una versión por comprensión porque es una primitiva menos "simple". Por esta razón es muy probable que Python 3000 no tenga más reduce, ya que en la mayoría de los casos es más sencillo (y siempre es más explícito) usar el buclecito como hice arriba.
Esto fue programación funcional en Python, espero que les haya gustado.
Saludos
