Lisp y Scheme

Una de las cosas que me llaman la atención es la convicción tan grande que los programadores de Lisp tienen en el poder de sus paréntesis.

Aún en el contexto de desarrollo Web Paul Graham ha llamado a Lisp su arma secreta, y en el manual de como convertirse en un Hacker de Eric Steven Raymond Lisp se presenta como un experiencia mística. Peter Norvig, en Teach Yourself Programming in Ten Years recomienda aprender lenguajes que soporten abstracción de clases (como Java), abstracción funcional (como Lisp), abstracción sintáctica (como Lisp), especificación declarativa (como Prolog), corutinas (como Scheme), y paralelismo (como Sisal).

El enfoque funcional parece ser fundamental y, por ejemplo, el equipo de desarrollo de C# ha hecho un esfuerzo por soportar este paradigma en la nueva versión a través del mecanismo de delegados.

Es claro que el río suena porque agua lleva. Para el interesado hay material introductorio abundante pero lograr la iluminación requerirá tiempo y esfuerzo.

Para Lisp, como lo indica su nombre, todo son listas y los comando básicos (constructors, selectors y recognizers) son para manipular las mismas:

quote para diferenciar una lista de una llamada a función.
first y rest para separar listas en sus partes.
cons para construir listas.
null y consp para ver si una lista esta vacía.
member para verificar si un elemento es miembro de una lista.
append para unir listas.

Lisp tiene varios dialectos: Common Lisp y Scheme son algunos de los más difundidos. CLisp es un implementación de Common Lisp y Visual CLisp es un puerto a Windows con un GUI. Otra alternativa es CMUCL.

Dorai Sitaram tiene un sitio con ligas a recursos sobre Scheme y Common Lisp, incluyendo un tutorial bastante bueno.

drscheme incluye varias implementaciones de Scheme bajo una interfaz común orientada a un ambiente académico.
Las funciones de Scheme para manipular listas son:

cons
toma dos argumentos y regresa un par o lista.
(cons '1 '2)              is   (1 . 2)

 

El primer ejemplo es un par y los otros son listas. Pares o listas se pueden utilizar para implementar registros.

carregresa el primer miembro de una lista o par.

(car '(123 245 564 898))             is   123

 

cdrregresa la lista sin el primer elemento.

(cdr '(7 6 5))               is  (6 5)

 

null?regresa #t si el objeto es la lista nula. En cualquier otro caso regresa la lista nula.listregresa un alista construida de los argumentos.

(list 'a)                          is  (a)

 

lengthregresa la longitud de la lista.

     (length '(1 3 5 9 11)) is  5

 

reverseregresa la lista invertida.

     (reverse '(1 3 5 9 11)) is  (11 9 5 3 1)

 

appendregresa la concatenación de dos listas.

     (append '(1 3 5)  '(9 11))  is  (1 3 5 9 11)

 

Expresiones condicionales son de la forma:

(if test-exp then-exp)
(if test-exp then-exp else-exp).

Definiciones son de la forma:

     (define id exp)

 

Expresiones Lambda son funciones anónimas de la forma:

         (lambda (id...) exp )

 

Definiciones locales se introducen con las funciones let, let* y letrec. let se aplica en paralelo, let* es secuencial, y letrec permite definiciones recursivas.

 

  • apply regresa el resultado de aplicar el primer argumento al segundo.

 

1 ]=>  (apply + '(7 5)) 

;Value:   12 

1 ]=>  (apply max '(3 7 2 9))
 

;Value:   9

 

  • map regresa una lista que es el resultado de aplicar el primer argumento a cada elemento del segundo.

 

1 ]=>   (map odd? '(2 3 4 5 6)) 

;Value: (() #T () #T ())

Referencias:

The Allegro Common Lisp Open Source Center

Allegro CL

http://www.cs.berkeley.edu/~fateman/generic/

Richard J. Fateman

Algoritmos en Scheme

Taller sobre Scheme

Hobbit versión 5 compila R4RS Scheme a código C, que se puede usar con SCM Scheme Implementation

El paquete SLIB es una librería portable del lenguaje Scheme que funciona en varias plataformas e implementaciones, incluyendo Guile.