- Paradigma Funcional
Historia - Cálculo
Lambda - Características
- Lenguajes
Funcionales - Funciones
- Scheme
- Historia
- Conclusión
- Bibliografía
El objetivo del
paradigma
funcional es conseguir lenguajes expresivos y
matemáticamente elegantes, en los que no sea necesario
bajar al nivel de la máquina para describir el proceso
llevado a cabo por el programa, y
evitando el concepto de
estado del
cómputo. La secuencia de computaciones llevadas a cabo por
el programa se regiría única y exclusivamente por
la reescritura de definiciones más amplias a otras cada
vez más concretas y definidas, usando lo que se denominan
definiciones dirigidas.
Todo esto con el objetivo de familiarizar a los
estudiantes con un lenguaje
elegante en el cual se pueda manejar más fácilmente
y así los programas sean
menos extensos y complejos.
Otro de los objetivos
primordiales de dicho paradigma es buscar satisfacer las
necesidades del usuario con respecto a operaciones
matemáticas y convertirse en un lenguaje
más expresivo.
Sus orígenes provienen del
Cálculo Lambda (o
λ-cαlculo), una teoría
matemática
elaborada por
Alonso Church como apoyo a sus estudios
sobre
Computabilidad. Un
lenguaje funcional es, a grandes rasgos,
un
azúcar sintáctico del
Cálculo
Lambda.
Los orígenes teóricos del modelo
funcional se remontan a la década del 30, mas precisamente
al año 1934, cuando Alonso Church introdujo un modelo
matemático de computación llamado lambda
calculo.
A pesar de que en esta época las computadoras
aun no existían el lambda cálculo se puede
considerar como el primer lenguaje funcional de la historia y sus fundamentos
fueron la base de toda la
teoría de la programación funcional y de los lenguajes
funcionales desarrollados posteriormente. Se puede decir que los
lenguajes funcionales modernos son versiones de lambda
cálculo con numerosas ayudas
sintácticas.
Aunque cuando aparece el cálculo lambda,
aún no existían las computadoras, resulta ser una
herramienta simple que se adelanta a su época, que abarca
dos operaciones:
- Definir alguna(s) función(es) de un solo argumento y con
un cuerpo específico, denotado por la siguiente
terminología: lx.B, en donde:
- x: Define el parámetro o argumento
formal. - B: Representa el cuerpo de la
función. - Es decir f(x) = B.
- x: Define el parámetro o argumento
- REDUCCION:
Consiste en aplicar alguna de las funciones
creadas, sobre un argumento real (A); resultado de sustituir
las ocurrencias del argumento formal (x), que aparezcan en el
cuerpo (B) de la función, con el argumento
(A),
es decir: (lx.B)
Ejemplo:
(lx.(x+5))3, indica que en la expresión x +
5, debemos sustituir el valor de x
por 3.
Cuando ya no es posible reducir una función, se
dice que ésta se encuentra en su estado normal, o sea
hemos encontrado el valor de la función, que
dependerá únicamente de los argumentos y siempre
tendrá la consistencia de regresar el mismo valor para los
mismos argumentos.
Lo anterior es la transferencia referencial y al no
contar con variables
globales, permiten al sistema la
ejecución de procesos en
forma paralela para incrementar su eficiencia.
Sobre estos simples conceptos está basada la
programación funcional, aunque existen otros, usados para
identificarla y aumentan su potencial en el desarrollo de
aplicaciones.
Los programas escritos en un lenguaje funcional
están constituidos únicamente por definiciones de
funciones, entendiendo éstas no como subprogramas
clásicos de un lenguaje imperativo, sino como funciones
puramente matemáticas, en las que se verifican ciertas
propiedades como la
transparencia referencial (el significado
de una expresión depende únicamente del significado
de sus subexpresiones), y por tanto, la carencia total de
efectos laterales.
Otras características propias de estos lenguajes
son la no existencia de asignaciones de variables y la falta de
construcciones estructuradas como la secuencia o la
iteración (lo que obliga en la práctica a que todas
las repeticiones de instrucciones se lleven a cabo por medio
de
funciones recursivas).
Existen dos grandes categorías de lenguajes
funcionales: los funcionales puros y los híbridos. La
diferencia entre ambos estriba en que los lenguajes funcionales
híbridos son menos dogmáticos que los puros, al
admitir conceptos tomados de los lenguajes procedimentales, como
las secuencias de instrucciones o la asignación de
variables.
En contraste, los lenguajes funcionales puros tienen una
mayor potencia
expresiva, conservando a la vez su transparencia referencial,
algo que no se cumple siempre con un lenguaje funcional
híbrido.
Entre los lenguajes funcionales puros, cabe destacar
a Haskell
y Miranda.
Los lenguajes funcionales híbridos más conocidos
son Lisp,
Scheme,
Ocaml
y Standard
ML (estos dos últimos, descendientes del
lenguaje ML).
La programación funcional, es un modelo basado en
la evaluación
de funciones matemáticas, entendidas como mecanismos para
aplicar ciertas operaciones sobre algunos valores o
argumentos, para obtener un resultado o valor de la
función para tales argumentos.
Sin embargo, tanto argumentos como resultado de una
función, pueden ser otra función, o incluso la
misma, tal como una forma de recursividad, que constituye una
poderosa herramienta de la programación
funcional
Los matemáticos desde hace un buen tiempo
están resolviendo problemas
usando el concepto de función. Una función
convierte ciertos datos en
resultados. Si supiéramos cómo evaluar una
función, usando
la computadora, podríamos resolver
automáticamente muchos problemas.
Así pensaron algunos matemáticos, que no
le tenían miedo a la máquina, e inventaron los
lenguajes de
programación funcionales. Además, aprovecharon
la posibilidad que tienen las funciones para manipular datos
simbólicos, y no solamente numéricos, y la
propiedad de las funciones que les permite
componer, creando de esta manera, la oportunidad para resolver
problemas complejos a partir de las
soluciones a otros más
sencillos.
También se incluyó la posibilidad de
definir funciones recursivamente.
Un lenguaje funcional ofrece conceptos que son muy
entendibles y relativamente fáciles de manejar para todos
los que no se durmieron en las clases de matemáticas.
El lenguaje funcional más antiguo,
y seguramente el más popular hasta la fecha, es LISP,
diseñado por McCarthy [1]
en la segunda mitad de los años 50. Su área de
aplicación es principalmente la
Inteligencia Artificial. En la
década de los 80 hubo una nueva ola de interés
por los lenguajes funcionales, añadiendo la
tipificación y algunos conceptos modernos de
modularización y polimorfismo, como es el caso del
lenguaje ML.
Programar en un lenguaje funcional significa construir
funciones a partir de las ya existentes. Por lo tanto es
importante conocer y comprender bien las funciones que conforman
la base del lenguaje, así como las que ya fueron definidas
previamente. De esta manera se pueden ir construyendo
aplicaciones cada vez más complejas.
La desventaja de este modelo es que resulta bastante
alejado del modelo de la máquina de von Neumann y,
por lo tanto, la eficiencia de ejecución de los
intérpretes de lenguajes funcionales no es comparable con
la ejecución de los programas imperativos precompilados.
Para remediar la deficiencia, se está buscando utilizar
arquitecturas paralelas que mejoren el
desempeño de los programas
funcionales, sin que hasta la fecha estos intentos tengan un
impacto real importante.
Los dos mecanismos básicos presentados
anteriormente se corresponden con los conceptos de
abstracción funcional y aplicación de
función; si le agregamos un conjunto de identificadores
para representar variables se obtiene lo mínimo necesario
para tener un lenguaje de
programación funcional. Lambda calculo tiene el
mismo
poder computacional que cualquier lenguaje
imperativo tradicional.
Las ventajas de tener un lenguaje tan simple
son:
- Permite definiciones
simples. - Facilita el estudio de aspectos
computacionales. - Su carácter
formal facilita la demostración de
propiedades.
Aplicaciones
- Compilación de lenguajes
funcionales. - Especificar semántica a lenguajes
imperativos. - Formalismo para definir otras
teorías.
La crítica
de John Backus a los "lenguajes convencionales de von Neumann"
llamó la atención hacia la programación
funcional (hacia 1978). El estilo de programación adoptado
por Backus fue denominado FP (Functional Programming).
El componente básico de los lenguajes funcionales
es la noción de función y su estructura de
control esencial
la aplicación de una función. Entre los lenguajes
funcionales se encuentran ISWIM, ML, LISP y todos sus derivados,
como Scheme. Las características fundamentales de los
lenguajes funcionales de programación son, según
[SET92]:
1. El valor de una expresión depende sólo
de los valores de
sus subexpresiones, si las tiene. La programación
funcional pura es una programación sin asignaciones. En
realidad, la mayoría de los lenguajes funcionales son
impuros, ya que permiten asignaciones. Sin embargo, su estilo de
programación es diferente al de los lenguajes de
programación imperativa.
2. Almacenamiento
implícito. El programador no debe preocuparse en manejar
el almacenamiento de datos. Una consecuencia de esto es que la
implementación del lenguaje debe realizar una
"recolección de basura" para
recuperar la memoria que
se ha usado y no se volverá a utilizar.
3. Las funciones son valores de primera clase. Una
función puede ser el valor de una expresión,
pasarse como argumento o colocarse en una estructura de
datos. Esto permite potentes operaciones.
Al decir que un lenguaje de programación es
funcional, se suele hacer referencia al paradigma de
programación funcional.
En términos general, al desarrollar software en el paradigma de
programación, en contraste con el paradigma de
programación imperativo, se tiende a enfatizar más
la evaluación de expresiones que la ejecución
secuencial de comandos.
En el fondo, para ejecutar programas los computadores
ejecutan, de manera secuencial, instrucciones de código
de máquina. De cierta forma, ésto hace que los
lenguajes imperativos sean más cercanos a la manera en que
funcionan los computadores, al forzar a los programadores a
formular sus algoritmos
como una serie de pasos que se realizarán de manera
secuencial.
Los lenguajes funcionales, por otro lado, son más
cercanos a la manera en que funciona la mente humana, pues
tienden a permitirle a los programadores describir sus algoritmos
como expresiones que serán evaluadas.
Hay varias consecuencias del énfasis en la
evaluación de expresiones que son comunes a la
mayoría de lenguajes funcionales:
- Los procedimientos son ciudadanos de primera
categoría Los procedimientos y funciones son
objetos visibles que pueden ser almacenados dentro de
estructuras complejas, pasados como
argumentos, construidos en tiempo de ejecución y
manipulados al igual que otros tipos como los números
y las cadenas. - Manejo automático de memoria
El programador no necesita llevar un registro
manual de la
memoria utilizada por cada objeto y liberarla; la
implementación del lenguaje se encarga de eso de
manera automática.
Los lenguajes funcionales han permanecido en uso por
mucho tiempo y han mostrado todo el poder de su
gran nivel de expresividad. Al permitir la creación de
procedimientos en tiempo de ejecución, permiten un gran
nivel de modularidad que, de acuerdo con sus proponentes,
difícilmente puede alcanzarse en otros paradigmas de
programación.
Dentro de los lenguajes funcionales se encuentran Lisp,
Haskell, CaML y muchos otros.
El lenguaje provee algunas funciones basicas, que son
primitivas para construir funciones más complejas. Se
definen algunas estructuras para representar datos en los
parámetros y resultados de las funciones. Este paradigma
normalmente se implementa mediante interpretadores, pero tambien
se pueden compilar.
Los primeros ordenadores se construyeron en los
años cuarenta. Pronto se almacenaron los programas en la
memoria del ordenador, haciendo que los primeros lenguajes de
programación hicieran su entrada. En aquel tiempo el uso
de un ordenador era muy costoso y era lógico que el lenguaje de
programación guardara mucha relación con la
arquitectura
del ordenador.
Un ordenador consta de una unidad de control y una
memoria. Por eso un programa consistía en instrucciones
para cambiar el contenido de la memoria. La unidad de control se
encargaba de ejecutarlas. De esta manera se creo el estilo de
programación imperativa. Los lenguajes de
programación imperativa como Pascal y C se
caracterizan por la existencia de asignaciones ejecutadas
consecutivamente.
Antes de la existencia de los ordenadores se inventaron
métodos
para resolver problemas. Por tanto, no existía la
necesidad de hablar en términos de una memoria que cambie
por instrucciones en un programa.
En la matemática de los últimos
cuatrocientos años son muy importantes las funciones.
Estas establecen la relación entre los parámetros
(la ‘entrada’) y el resultado (la
‘salida’) de procesos definidos. Con cada
computación, el resultado depende de una u otra forma de
los parámetros. Por esa razón, una función
es una buena manera de especificar una computación. Esta
es la base del estilo de programación funcional. Un
‘programa’ consiste en la definición de una o
mas funciones.
Para la ejecución de un programa, se dan
parámetros a una función y el ordenador tiene que
calcular el resultado. Con este tipo de computación existe
libertad en la
manera de ejecución. ¿Por qué tendría
que describirse en qué orden deben ejecutarse las
computaciones parciales?
Con el tiempo, al bajar los precios de los
ordenadores y al subir los precios de los programadores, llega a
ser más importante describir las computaciones en un
lenguaje que esté más cerca del mundo del hombre, que
cerca del ordenador. Los lenguajes funcionales se unen a la
tradición matemática y no están muy
influidos por la arquitectura concreta del ordenador.
Scheme es un lenguaje funcional, derivado de LISP.
Scheme es un lenguaje compacto con un alto grado de
abstracción, por lo cual resulta adecuado para cursos
introductorios de computación, donde el énfasis
está en la metodología de resolución de
problemas. Scheme permite resolver problemas complejos con
programas cortos y elegantes. De este modo, el lenguaje se
convierte en un aliado para resolver problemas, no un problema
más que resolver.
El desarrollo de los lenguajes funcionales ha sido
influenciado a lo largo de la historia por muchas fuentes, pero
ninguna tan grande ni fundamental como el trabajo de
Alonzo Church en el Cálculo Lambda.
El Cálculo Lambda fue asimismo el fundamento en
que se basó el desarrollo del Lisp, pero el propio John
McCarthy ha negado ese hecho3. El impacto del Cálculo
Lambda en el desarrollo inicial del Lisp fue mínimo y no
ha sido sino hasta recientemente que el popular lenguaje ha
comenzado a evolucionar de acuerdo con los ideales del mismo. Por
otra parte, Lisp ha tenido una gran influencia en el desarrollo
de los lenguajes funcionales que le siguieron.
La motivación
original de McCarthy para desarrollar Lisp fue el deseo de contar
con un lenguaje para procesamiento de listas algebraicas que
pudiera usarse para llevar a cabo investigación en inteligencia
artificial.
Uno de los primeros intentos por desarrollar un lenguaje
de tal naturaleza fue
realizado por McCarthy, con el llamado FLPL (FORTRAN – compiled
List Processing Language), que se implementó en el FORTRAN
con que contaba la IBM 704 en 1958. Durante los años
subsiguientes McCarthy diseñó, refinó e
implementó Lisp (List Processor), en parte porque FLPL no
contaba con recursividad ni con condicionales dentro de las
expresiones.
Lisp no es sólo uno de los lenguajes más
viejos que existen, sino también el primero en
proporcionar recursividad, funciones como ciudadanos de primera
clase, recolección de basura y una
definición formal del lenguaje (escrita asimismo en Lisp).
Las diversas implementaciones de Lisp desarrolladas a
través de los años han sido también pioneras
en cuanto al uso de ambientes integrados de programación,
los cuales combinan editores, intérpretes y
depuradores.
Las primeras implementaciones de Lisp tuvieron, sin
embargo, algunos problemas que las hicieron perder popularidad,
como por ejemplo su tremenda lentitud para efectuar
cálculos numéricos, su sintaxis basada por completo
en paréntesis que suele causar gran confusión entre
los usuarios novatos y su carencia de tipos que hace
difícil la detección de errores y el desarrollo de
compiladores.
Además, problemas adicionales tales como la
carencia de verdaderas funciones como ciudadanos de primera clase
y el uso de reglas de ámbito dinámicas, bajo las
cuales el valor de una variable libre se toma del ambiente de
activación, hicieron que Lisp se mantuviera durante un
buen tiempo como un lenguaje restringido a los laboratorios de
investigación, lejos del alcance de un número
significativo de usuarios. El mismo McCarthy afirmó que su
lenguaje no era apropiado "para los programadores novatos o los
no programadores", pues se requería una cierta cantidad de
"conocimientos sofisticados para apreciar y usar el lenguaje
efectivamente".
A partir de 1962, el desarrollo del Lisp divergió
en un gran número de dialectos, entre los que destacan
MacLisp y ZetaLisp en el Instituto Tecnológico de
Massachusetts (MIT), Franz Lisp en la Universidad de
California en Berkeley, ICI-Lisp en la Universidad de Stanford, y
el InterLisp, un producto
comercial desarrollado por Bolt, Boranek y Newman (en un laboratorio de
investigación privado de los Estados
Unidos).
En el otoño de 1975 Gerald Jay Sussman y Guy
Lewis Steele Jr. se encontraban estudiando la teoría de
los actores como un modelo de computación desarrollada por
Carl Hewitt en MIT.
El modelo de Hewitt estaba orientado a objetos y con una
fuerte influencia del Smalltalk. De acuerdo con él, cada
objeto era una entidad computacionalmente activa capaz de recibir
y de reaccionar a los mensajes. A estos objetos y los mensajes
que intercambiaban, Hewitt los llamó actores. Dado que
Sussman y Steele afrontaban dificultades para entender algunos
aspectos teóricos y prácticos del trabajo de
Hewitt, decidieron construir un pequeño intérprete
de este lenguaje usando MacLisp, a fin de poder experimentar con
él. Como Sussman había estado estudiando Algol en
aquella época, le sugirió a Steele comenzar con un
dialecto de Lisp que tuviera reglas de ámbito
estático (i.e., el valor de una variable libre se toma de
su ambiente de definición).
Esta decisión les permitió crear actores
con la misma facilidad con que se crean las funciones en Lisp (y
usando casi los mismos mecanismos). El paso de mensajes se
podría entonces expresar sintácticamente en la
misma forma en que se invoca una función. La única
diferencia entre un actor y una función era que una
función regresaba un valor y un actor no regresaba nada,
sino que más bien invocaba una continuación, o sea,
otro actor que sabía de su existencia.
Sussman y Steele se sintieron tan satisfechos con su
mini-intérprete que decidieron llamarlo "Schemer",
pensando que con el tiempo se convertiría en otro lenguaje
que se pudiera utilizar en inteligencia
artificial, tal y como PLANNER, el lenguaje desarrollado por
Hewitt. Sin embargo, el sistema operativo
ITS limitaba los nombres a 6 letras, por lo que el apelativo del
intérprete hubo de ser truncado a "Scheme", que es como se
le conoce hoy en día.
Persuadidos de que su intérprete parecía
capturar muchas de las ideas que circulaban entonces sobre
lenguajes de programación, Sussman y Steele decidieron
publicar la definición de Scheme en la forma de un memo
del laboratorio de inteligencia artificial del MIT. Esta primera
definición del lenguaje era sumamente austera, con un
mínimo de primitivas (una por concepto), pero marcó
el inició de lo que se convertiría en un lenguaje
de programación sumamente popular en las esferas
académicas.
En 1976, Sussman y Steele publicaron dos
artículos en los que se hablaba sobre semántica de
los lenguajes de programación usando Scheme: "Lambda: The
Ultimate Imperative" y "Lambda: The Ultimate Declarative", en los
cuales los autores enfatizarían el hecho de que Scheme
podía soportar eficientemente los principales paradigmas
de programación actuales (i.e., imperativo, funcional y
orientado a objetos). Esta última publicación se
convirtió de hecho en la propuesta de tesis de
maestría de Steele, que culminó en el desarrollo de
un compilador de Scheme llamado RABBIT.
Históricamente, Scheme contribuyó a
estrechar la brecha entre los teóricos (que estudiaban el
Cálculo Lambda y el modelo de actores) y los
prácticos (implantadores y usuarios de Lisp) en el
área de lenguajes de programación. Además,
Scheme hizo la semántica denotacional mucho más
accesible a los programadores y proporcionó una plataforma
operacional que permitiera a los teóricos realizar sus
experimentos.
Por su reducido tamaño, no había necesidad de tener
una versión centralizada del lenguaje que tuviera que
soportar un gran número de plataformas, como
sucedía con Lisp.
De tal forma, brotaron por todas partes implementaciones
y dialectos de Scheme hacia inicios de los 80. Un ejemplo es el
Scheme 311 [11],
desarrollado en la Universidad de Indiana varios años
antes de que alguien hiciera un intento por producir una
implementación aislada del lenguaje (i.e., que no tuviera
que montarse sobre Lisp).
Hoy en día Scheme es un lenguaje simple, pero
poderoso; pequeño, pero flexible. Su naturaleza lo hace
ideal para la enseñanza, incluso como primer lenguaje de
programación, por su notable facilidad para incorporar
diversos paradigmas con sólo un puñado de
primitivas.
Como lenguaje imperativo, conserva la pureza y elegancia
que le proporcionan la recursividad y las funciones de orden
superior, superando así a muchos de los lenguajes que hoy
gozan de gran popularidad, tales como Pascal y C. Como lenguaje
orientado a objetos, hace alarde de un sistema de paso de
mensajes y de manipulación de objetos equiparable
únicamente al de Smalltalk. Su mecanismo de continuaciones
proporciona procedimientos de escape como ciudadanos de primer
orden, condenando a la obsolescencia a los mecanismos similares
con que cuentan otros lenguajes.
El uso de streams permite implementar la
evaluación concisa, convirtiendo al lenguaje en una
herramienta idónea para cursos avanzados de lenguajes de
programación. Una de sus pocas desventajas estriba en su
carencia de tipos, aunque existen versiones de Scheme que
incorporan un sistema similar al de ML (por ejemplo, Scheme
48).
Desde una perspectiva más pragmática,
podemos decir que su sintaxis es extremadamente simple, lo que
permite que el lenguaje pueda dominarse fácilmente en
sólo 6 meses. Los estudiantes suelen preferirlo, sobre
todo, cuando se trata del primer lenguaje de programación
que aprenden, y los instructores lo elogian porque facilita la
enseñanza de ideas de abstracción y diseño
de algoritmos, tan útiles para formar buenos
programadores.
Con la sabia filosofía de proporcionar
sólo una primitiva que haga lo que queremos en vez de
varias, como en otros lenguajes, Scheme se erige en la cima de
los lenguajes preferidos por las nuevas generaciones, ya no
sólo como una mera curiosidad científica, como se
vió a Lisp en otra época, sino como una herramienta
efectiva que sirve para aprender a programar y a resolver
problemas del mundo real.
La
página de Scheme
En qué idioma deseas navegar en este site?
…
webdia.cem.itesm.mx/ac/rtrejo/scheme.html
Scheme. Scheme es un dialecto de Lisp creado a
mediados de los 70 por Guy Lewis
Steele Jr. … schemers.org es un completo sitio sobre
Scheme. …
www.rodoval.com/paginalen.php?len=Scheme
Manual de
referencia de Scheme 1 El lenguaje de programación
…
Formato de archivo:
PDF/Adobe Acrobat –
Versión en HTML
Page 1. Manual de referencia de Scheme 1 El lenguaje de
programación Scheme
En cualquier lenguaje tenemos palabras que se combinan
…
www.cs.us.es/documentacion/scheme.pdf
Introducción a la programación con
SCHEME
José Helo Guzmán, Cartago: Editorial
Tecnológica de Costa Rica,
2000
ISBN 9977-66-113-8
Programación Funcional 2004
… paradigma de programación funcional. exploren y
utilicen con seguridad los
conceptos del paradigma funcional. conozcan las
principales …
groupfia.info.unlp.edu.ar/ fcional/objetivos.php?javascript=0
Lenguaje Funcional Miranda –
Monografias.com
… mediante relaciones entre objetos o entidades.
Evolución del paradigma
funcional.
Lambda calculo. Los orígenes teóricos del modelo
…
www.monografias.com/trabajos16/
lenguaje-miranda/lenguaje-miranda
Las virtudes de la programción
funcional
… Mi intención con esta nota (y las dos que le
seguirán) es ilustrar como el paradigma
Funcional es _muchísimo_ más expresivo que
el Imperativo, mucho más …
mail.pm.org/pipermail/caracas-pm/
2002-November/000245.html
Tatiana Macchiavello