En ciencias
de la computación, la programación
funcional es un paradigma
de programación declarativa basado en la utilización
de funciones aritméticas que no
maneja datos mutables o de estado. Enfatiza la aplicación de funciones, en
contraste con el estilo de programación imperativa, que enfatiza los cambios de
estado.
La programación funcional tiene sus raíces
en el cálculo
lambda, un sistema formal desarrollado en los
años 1930 para investigar la definición de función, la aplicación de las
funciones y la recursión.
Los lenguajes de programación funcional, especialmente los que
son puramente funcionales, han sido enfatizados en el ambiente académico
principalmente y no tanto en el desarrollo de software comercial. Sin embargo,
lenguajes de programación importantes tales como Scheme, Erlang, Rust, Objective
Caml y Haskell,
han sido utilizados en aplicaciones comerciales e industriales por muchas
organizaciones.
La programación funcional también es utilizada en la industria a
través de lenguajes de dominio específico como R (estadística), Mathematica
(matemáticas simbólicas), J y K (análisis financiero), F# en Microsoft.NET y
XSLT (XML). Lenguajes de uso específico usados comúnmente como SQL y Lex/Yacc,
utilizan algunos elementos de programación funcional, especialmente al procesar
valores mutables. Las hojas de cálculo también pueden ser consideradas lenguajes
de programación funcional.
La programación funcional también puede ser desarrollada en
lenguajes que no están diseñados específicamente para la programación funcional.
En el caso de Perl,
por ejemplo, que es un lenguaje de programación imperativo, existe un libro que
describe como aplicar conceptos de programación funcional. JavaScript,
uno de los lenguajes más ampliamente utilizados en la actualidad, también
incorpora capacidades de programación funcional. Python también
incorpora particularidades de los lenguajes funcionales como listas de
comprensión y funciones de tratamiento de listas como matemática de conjuntos.
Java en su versión 8, esta incorporando la programación funcional, así como el
uso de las expresiones lambda.
Resumiendo, la programación funcional, o mejor dicho, los lenguajes de
programación 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 ejecución. Además los programas se
estructuran componiendo expresiones que se evalúan como funciones. Dentro de
los lenguajes funcionales tenemos Lisp, Scheme, Clojure, Haskell, OCaml y
Standard ML, entre otros. Estos lenguajes están diversidad de tipificación,
donde se encuentran lenguajes dinámicos, estáticos y estáticos fuertes
Para citar un ejemplo de mostrar un mensaje
“Debo
poner atención en clases”. La respuesta expresada en PHP
esta escrita a continuación. Donde PHP es un lenguaje dinámico, no necesita
declarar variables y es un lenguaje orientado a objetos con raíces imperativas. Sus instrucciones son paso
a paso, y no constituyen una única expresión 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 tipificación estática fuerte, requiere que
las variables sean declaradas con un tipo — la mayoría de las veces — y es
muy expresivo, donde el siguiente ejemplo dice repetir la cadena, tomar 500
elementos y con esa lista ejecutar la función monádica 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 atención en
clases" |
En Lisp sería similar, pero Lisp es de
tipificación dinámica y no necesita declarar variables, dando lugar a un
programa muy simple de una sola línea. Donde también 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 máquina virtual de Java o JVM
;;; codigo Lisp
(loop repeat 500 do (format t "Debo poner atencion en clases~%"))
|
Un ejemplo clásico para la conversión η
en Haskell, es reducir las llamadas a funciones en su combinador de
identidad. Por ejemplo se tiene la función f(g(x)), que en Cálculo Lambda se expresa como λx.(λy.y)x, se puede reducir a g(x), que se expresa como λy.y en
Cálculo Lambda. Esto expresado en Haskell, se vería como el siguiente
ejemplo, donde absN y absN’ son funciones equivalentes y
absN’ es la reducción η de absN.
absN :: Num a => a -> a
absN n = abs n
absN' :: Num a => a -> a
absN' = abs |
Actualmente los lenguajes orientados a
objetos más comunes están integrando características funcionales, como Java,
que acaba de incluir funciones
anónimas. Pero también están los lenguajes que a lo
largo de su historia han sido multi-paradigma, como Python, e implementa
características funcionales, procedurales y orientadas a objetos. El bien
conocido algoritmo para verificar si un RUT es válido 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 guión 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
validación se realiza utilizando expresiones o llamadas
a funciones, sin uso de variables con estado y
mutabilidad, donde cada llamada a una función 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 válido. 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)) |
|