LO QUE HIZO DIFERENTE A LISP
OriginalDecember 2001 (rev. May 2002)
(Este artículo surgió en respuesta a algunas preguntas en la lista de correo de LL1. Ahora está incorporado en Revenge of the Nerds.)
Cuando McCarthy diseñó Lisp a finales de la década de 1950, fue una desviación radical de los lenguajes existentes, el más importante de los cuales fue Fortran.
Lisp incorporó nueve ideas nuevas:
1. Condicionales. Un condicional es una construcción if-then-else. Los damos por sentado ahora. Fueron inventados por McCarthy en el curso del desarrollo de Lisp. (Fortran en ese momento solo tenía un condicional goto, basado estrechamente en la instrucción de bifurcación en el hardware subyacente.) McCarthy, quien estaba en el comité de Algol, obtuvo condicionales en Algol, de donde se extendieron a la mayoría de los demás lenguajes.
2. Un tipo de función. En Lisp, las funciones son objetos de primera clase -- son un tipo de datos como los enteros, las cadenas, etc., y tienen una representación literal, se pueden almacenar en variables, se pueden pasar como argumentos, etc.
3. Recursión. La recursión existía como concepto matemático antes de Lisp, por supuesto, pero Lisp fue el primer lenguaje de programación en admitirla. (Es discutiblemente implícito en hacer que las funciones sean de primera clase objetos.)
4. Un nuevo concepto de variables. En Lisp, todas las variables son efectivamente punteros. Los valores son lo que tienen tipos, no las variables, y asignar o enlazar variables significa copiar punteros, no a lo que apuntan.
5. Recopilación de basura.
6. Programas compuestos por expresiones. Los programas Lisp son árboles de expresiones, cada uno de los cuales devuelve un valor. (En algunos Lisps, las expresiones pueden devolver varios valores.) Esto contrasta con Fortran y la mayoría de los lenguajes posteriores, que distinguen entre expresiones y declaraciones.
Era natural tener esta distinción en Fortran porque (no es sorprendente en un lenguaje donde el formato de entrada eran tarjetas perforadas) el lenguaje era orientado a líneas. No se podían anidar declaraciones. Y así, mientras que se necesitaban expresiones para que las matemáticas funcionaran, no había ningún punto en hacer que algo más devolviera un valor, porque no podía haber nada esperando por él.
Esta limitación desapareció con la llegada de los lenguajes estructurados en bloques, pero para entonces ya era demasiado tarde. La distinción entre expresiones y declaraciones estaba arraigada. Se extendió desde Fortran a Algol y de ahí a ambos descendientes.
Cuando un lenguaje está hecho completamente de expresiones, puedes componer expresiones como quieras. Puedes decir ya sea (usando la sintaxis de Arc)
(if foo (= x 1) (= x 2))
o
(= x (if foo 1 2))
7. Un tipo de símbolo. Los símbolos difieren de las cadenas en que puedes probar la igualdad comparando un puntero.
8. Una notación para el código usando árboles de símbolos.
9. Todo el lenguaje siempre disponible. No hay una distinción real entre el tiempo de lectura, el tiempo de compilación y el tiempo de ejecución. Puedes compilar o ejecutar código mientras lees, leer o ejecutar código mientras compilas, y leer o compilar código en tiempo de ejecución.
Ejecutar código en tiempo de lectura permite a los usuarios reprogramar la sintaxis de Lisp; ejecutar código en tiempo de compilación es la base de las macros; compilar en tiempo de ejecución es la base del uso de Lisp como lenguaje de extensión en programas como Emacs; y leer en tiempo de ejecución permite que los programas se comuniquen usando s-expresiones, una idea recientemente reinventada como XML.
Cuando Lisp se inventó por primera vez, todas estas ideas estaban lejos de la práctica de programación ordinaria, que estaba dictada en gran medida por el hardware disponible a finales de la década de 1950.
Con el tiempo, el lenguaje predeterminado, encarnado en una sucesión de lenguajes populares, ha evolucionado gradualmente hacia Lisp. 1-5 ahora están muy extendidos. 6 está empezando a aparecer en la corriente principal. Python tiene una forma de 7, aunque no parece haber ninguna sintaxis para ello. 8, que (con 9) es lo que hace que las macros Lisp sean posibles, hasta ahora sigue siendo exclusivo de Lisp, quizás porque (a) requiere esos paréntesis, o algo igual de malo, y (b) si agregas ese último incremento de poder, no puedes reclamar haber inventado un nuevo lenguaje, sino solo haber diseñado un nuevo dialecto de Lisp ; -)
Aunque útil para los programadores actuales, es extraño describir Lisp en términos de su variación de los expedientes aleatorios que otros lenguajes adoptaron. Esa no fue, probablemente, la forma en que McCarthy lo pensó. Lisp no fue diseñado para corregir los errores en Fortran; surgió más como un subproducto de un intento de axiomatizar la computación.