You are on page 1of 7

Qu es la programacin funcional?

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.

Pongamos un ejemplo. La funcin factorial, imperativamente, se definira como para calcular


el factorial, coge un valor de entrada, rstale uno, asigna este valor a x, calcula el factorial de x,
asgnalo a y, y devuelve x por y. rdenes, rdenes. En cambio, funcionalmente se definira
como el factorial de n es n por el factorial de n-1. Es una mera diferencia de abstraccin,
pero los lenguajes funcionales te fuerzan a pensar en ese alto nivel y no tiene sentido hablar
de rdenes, igual que en Python no tiene sentido hablar de registros, porque estn situados a
un nivel inferior.

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.

Algunas caractersticas tpicas

Como consecuencia de todo esto, en los programas funcionales se encuentran algunas


caractersticas:

qsort [] = []

qsort (x:xs) =

qsort (filter (< x) xs) ++

[x] ++

qsort (filter (>= x) xs)


Implementacin de Quicksort en Haskell. Es bonita, eh? Pues las hay ms elegantes.

Transparencia referencial. Al no haber variables, no hay efectos laterales, es decir, al ejecutar


la funcin (aunque ya hemos visto que el concepto de ejecutar no existe como tal) no
cambiar nada fuera del entorno de sta. Tampoco depender para nada de lo que haya en
ese entorno. Se dice que una funcin tiene transparencia referencial si, para un valor de
entrada, produce siempre la misma salida. En programacin funcional esto es siempre as por
definicin. Esto permite la

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.

Altsima abstraccin. Los lenguajes funcionales implementan muchsimos mecanismos de


abstraccin que te hacen la vida muy, muy feliz. Un brutal sistema de tipos de datos,
polimorfismo en muchos niveles, y un montn de nuevos conceptos como funciones de orden
superior, functores, mnadas Las inevitables operaciones que no son puramente funcionales,
como la entrada/salida o los nmeros aleatorios, quedan envueltos en abstracciones que
resuelven la papeleta con elegancia.

Elegancia, legibilidad, flexibilidad. Por lo general, cuanto ms abstracto es un lenguaje, ms se


potencian estas caractersticas, por lo que los programas funcionales suelen ser ms claros,
ms concisos y ms bellos que sus contrapartidas en lenguajes imperativos (incluso en
preciosidades como Python o Ruby). El cdigo ms artstico que he visto nunca, con diferencia,
est en Haskell. Adems, la ausencia de entorno y de estado permite que, si ests leyendo una
funcin, slo tengas que retener en tu cabeza esa funcin, sin preocuparte de ms. Esto facilita
adems

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.

Y por qu no los usamos todos siempre?

No todo es tan bonito, claro. En la prctica, existen algunos inconvenientes a tener en cuenta.

max([H|T]) -> max2(T, H).

max2([], Max) -> Max;

max2([H|T], Max)

when H > Max -> max2(T, H);

max2([_|T], Max) -> max2(T, Max).


Mximo de una lista, en Erlang.

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.

Por dnde seguir

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.

En Haskell.org tienes infinidad de documentacin, incluido el fantstico buscador Hoogle, y


una comunidad muy dispuesta a ayudar.

(defn fib

([] (concat [0 1] (fib 0 1)))

([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?

DOMINGO 11 NOV 2012 | COMENTARIOS

La programacin funcional, o mejor dicho, los lenguajes de programacin funcionales, son


aquellos lenguajes donde las variables no tienen estado no hay cambios en stas a lo largo
del tiempo y son inmutables no pueden cambiarse los valores a lo largo de la ejecucin.
Adems los programas se estructuran componiendo expresiones que se evalan como
funciones. Dentro de los lenguajes funcionales tenemos Lisp, Scheme, Clojure, Haskell,
OCaml y Standard ML, entre otros. Estos lenguajes estn diversidad de tipificacin, donde se
encuentran lenguajes dinmicos, estticos y estticos fuertes.

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 */

for ($i = 0; $i < 500; $i++) {

echo "Debo poner atencion en clases";

}
?>

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.

module Main (main) where

-- 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.

;;; codigo Lisp

(loop repeat 500 do (format t "Debo poner atencion en clases~%"))

Un ejemplo clsico para la conversin en Haskell, es reducir las llamadas a funciones en su


combinador de identidad. Por ejemplo se tiene la funcin f(g(x)), que en Clculo Lambda se
expresa como x.(y.y)x, se puede reducir a g(x), que se expresa como y.y en Clculo
Lambda. Esto expresado en Haskell, se vera como el siguiente ejemplo, donde absN y absN
son funciones equivalentes y absN es la reduccin de absN.

absN :: Num a => a -> a

absN n = abs n

absN' :: Num a => a -> a


absN' = abs

Actualmente los lenguajes orientados a objetos ms comunes estn integrando


caractersticas funcionales, como Java, que acaba de incluir funciones anonimas. Pero
tambin estn los lenguajes que a lo largo de su historia han sido multi-paradigma, como
Python, e implementa caractersticas funcionales, procedurales y orientadas a objetos. El
bien conocido algoritmo para verificar si un RUT es vlido o no, se puede expresar
funcionalmente en Python como esta escrito en el siguiente ejemplo.

def val_rut(rut):

"""

Valida un string con un RUT con el guion incluido, retornando

cero si es valido.

Ejemplo: print(val_rut("22222222-2"))

"""

return cmp(rut[-1],

str((range(10) + ['K'])[

(11 - sum(map(lambda x: (int(x[0]) * x[1]),

zip(reversed(rut[:-2]),

(2 * range(2, 8))))) % 11)]))

Como se aprecia en el ejemplo, la validacin se realiza utilizando expresiones o llamadas a


funciones, sin uso de variables con estado y mutabilidad, donde cada llamada a una funcin
se puede reducir a un valor determinado, y como resultado final se tiene un valor cero o
distinto de cero que indica si el RUT es vlido. Este mismo algoritmo funcional, se puede
expresar en Haskell con llamadas muy similares, debido a que los nombres de las funciones y
funciones de alto orden son bastante comunes entre los lenguajes funcionales.

valRut :: String -> Bool

valRut s = (((['0'..'9'] ++ ['K'])

!! (11 - sum(zipWith (*)

(fmap digitToInt $ drop 2 $ reverse s)

(take 10 $ cycle [2..7])) `mod` 11)) == (last s))

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.

Personalmente creo que es importante aprender algo de programacin funcional porque de


alguna forma cambia la perspectiva que uno tiene de los programas. Uno generalmente esta
acostumbrado a pensar en los programas como si fuesen una lista ordenada de instrucciones
a seguir, cuando generalmente esa misma lista ordenada de instrucciones a seguir puede ser
expresada como una funcin y ms aun, como una funcin pura.

You might also like