Professional Documents
Culture Documents
Antes de nada, quiero aclarar que durante el artculo hablar basndome en un lenguaje
funcional en concreto: Haskell. En otros lenguajes puede haber implementaciones ligeramente
diferentes, al igual que C++ y Python implementan la POO de manera distinta, pero la idea de
fondo ser siempre la misma.
Los lenguajes habituales se basan, en mayor o menor medida, en realizar una serie de pasos,
en definir lo que las cosas hacen; esto se conoce como programacin imperativa. En
programacin funcional, definiremos ms bien lo que las cosas son.
El propio nombre nos da una pista de la caracterstica fundamental de este paradigma: se basa
fuertemente en un concepto de funcin algo diferente al que estamos acostumbrados, ms
cercano al matemtico que su contraparte en los lenguajes imperativos. No hay variables, por
lo que estas funciones slo tratarn con sus valores de entrada y con constantes predefinidas;
no tienen ms posibilidad de accin.
Bsicamente, un programa funcional es aquel que slo est compuesto de funciones que se
limitan a hacer corresponder cada elemento que se le pase como argumento con un valor.
qsort [] = []
qsort (x:xs) =
[x] ++
Evaluacin perezosa (Lazy evaluation). Para una mente acostumbrada a lo imperativo esto
cuesta de entender, as que atencin. Al no tener que seguir una serie de rdenes, una tras
otra, algunos los lenguajes funcionales slo evalan lo que les es requerido en cada momento.
Esto permite cosas como el cdigo Haskell take 5 [1..], que significa coger los cinco primeros
nmeros de una lista infinita de nmeros empezando por el 1. En un lenguaje imperativo,
esto llevara a un bucle infinito mientras se genera la lista. En Haskell, slo se genera lo que se
necesita; en este caso, los cinco primeros nmeros. Esto puede redundar en una ejecucin ms
eficiente y un cdigo ms claro y cercano al matemtico.
Facilidad para las pruebas y la depuracin. Gracias a la transparencia referencial, hacer unit
testing en lenguajes imperativos es trivial. Adems, el alto nivel hace que los errores lo tengan
difcil para esconderse por el cdigo, por lo que suelen salir programas muy fiables.
No todo es tan bonito, claro. En la prctica, existen algunos inconvenientes a tener en cuenta.
max2([H|T], Max)
Mayor dificultad inicial. Aunque sean muy fciles de entender y mantener, suele ser ms difcil
escribir un programa funcionalmente, sobre todo para mentes acostumbradas a lo imperativo.
La gran variedad de conceptos complejos a tener en cuenta hace difcil dominar el lenguaje y
producir buen cdigo. La ausencia de variables de estado, aunque nos facilite la vida a
posteriori, hace que tengas que comerte ms la cabeza al sentarte a picar lneas y planificar
muy bien lo que vas a hacer, y esto en entornos de produccin puede no ser lo ms
conveniente. De hecho, esto despierta hasta algunos odios...
Falta de recursos. Al estar tan poco extendidos, faltan la gran cantidad de recursos (libreras,
frameworks, etc.) existentes para otros lenguajes; aunque ltimamente, que se vuelven a
poner relativamente de moda, cada vez salen ms soluciones, como este binding de Cocoa
para Haskell.
Slo hemos visto una torpe introduccin a la punta del iceberg. Si eres un sanamente inquieto
programador, te habr picado el gusanillo de probar todo esto tan raro. Afortunadamente, la
comunidad de Haskell parece ms preocupada por documentar el lenguaje que de escribir
software, por lo que recursos de aprendizaje hay de sobra y recomiendo empezar por este
lenguaje.
Try Haskell, una amena introduccin interactiva online que te dejar con ganas de ms.
Learn you a Haskell, uno de los mejores tutoriales de todos los tiempos, extremadamente
divertido.
(defn fib
([a b] (lazy-cons (+ a b)
(fib b (+ a b)))))
Secuencia infinita Fibonacci en Clojure. Para usar con lazy evaluation, claro.
Si te manejas con Java, puede que te interese ms Clojure, que utiliza su mquina virtual;
recientemente en .NET se ha incorporado el lenguaje F#.
PROGRACION FUNCIONAL
Qu Es La Programacin Funcional?
En los lenguajes funcionales las instrucciones cclicas como for, while y do-while no existen.
Todo se procesa usando recursividad y funciones de alto orden. Esto se debe a los
fundamentos matemticos de la mayora de los lenguajes funcionales, principalmente con
bases en el sistema formal diseado por Alonzo Church para definir cmputos y estudiar las
aplicaciones de las funciones llamado Clculo Lambda. En este sistema formal se puede
expresar recursividad en las funciones, y entre otras cosas interesantes, se pueden expresar
combinadores funciones sin variables libres como el Combinador de Punto Fijo o Y-
Combinator, que expresa recursividad sin hacer llamadas recursivas. En el Clculo Lambda
existen tres transformaciones esenciales, la conversin , la reduccin y la conversin .
En la conversin se sustituyen los nombres de las variables para dar mas claridad a la
aplicacin de las funciones, por ejemplo evitando duplicados en sus nombres. En la
reduccin se traza el llamado de las funciones sustituyendo las funciones por sus
expresiones resultantes. Finalmente en las conversiones se busca las equivalencias de
trazado de funciones sustituyndolas por sus equivalentes. Estas transformaciones tambin
pueden ser aplicadas en los lenguajes funcionales o en su mayora dando lugar
lenguajes que cuentan con una gran expresividad y consistencia.
Les pondr el clsico ejemplo del chiste geek del castigo Debo poner atencin en clases. La
respuesta geek expresada en PHP esta escrita a continuacin. Donde PHP es un lenguaje
dinmico, no necesita declarar variables y es un lenguaje orientado a objetos con races
imperativas. Sus instrucciones son paso a paso, y no constituyen una nica expresin
reducible.
<?php
/* codigo PHP */
}
?>
Si usamos Haskell como ejemplo, que es un lenguaje funcional con tipificacin esttica
fuerte, requiere que las variables sean declaradas con un tipo la mayora de las veces y
es muy expresivo, donde el siguiente ejemplo dice repetir la cadena, tomar 500 elementos y
con esa lista ejecutar la funcin mondica putStrLn, que esta hecha para el Monad IO e
imprime la el mensaje las 500 veces solicitada.
-- codigo Haskell
main :: IO ()
main = mapM_ putStrLn $ take 500 $ repeat "Debo poner atencion en clases"
En Lisp sera similar, pero Lisp es de tipificacin dinmica y no necesita declarar variables,
dando lugar a un programa muy simple de una sola linea. Donde tambin tenemos lenguajes
como Clojure, que es un dialecto de Lisp y soporta construcciones muy similares a las del
ejemplo en Lisp, dando lugar a programas expresivos y simples, pero que corren sobre la
mquina virtual de Java o JVM.
absN n = abs n
def val_rut(rut):
"""
cero si es valido.
Ejemplo: print(val_rut("22222222-2"))
"""
return cmp(rut[-1],
str((range(10) + ['K'])[
zip(reversed(rut[:-2]),
De estos dos ejemplos, se puede decir que son funciones puras, principalmente debido a que
no tienen variables libres y son una nica expresin sin estado y no mutable a lo largo de la
ejecucin. El problema de la pureza es conceptualmente algo que se idealiza en la
programacin funcional, siendo abordado de diferentes formas por diferentes lenguajes. El
objetivo es mantener las funciones y rutinas puras. En Haskell, con su abstraccin ms clsica
conocida con el nombre de Mnada, permite entregar pureza a expresiones que parecen no
ser puras, y en trminos muy sencillos el Mnada rene una identidad y una composicin de
funciones del tipo f(g(x)), todo a travs de un tipo de dato que permite componer funciones
sin abandonar ese tipo de dato y darle un aspecto procedural.