Loading...

QUÉ HIZO QUE LISP FUERA DIFERENTE

Original

Diciembre de 2001 (rev. Mayo de 2002)

(Este artículo surgió en respuesta a algunas preguntas en la lista de correo LL1. Ahora está incorporado en Revenge of the Nerds.)

Cuando McCarthy diseñó Lisp a finales de la década de 1950, fue un alejamiento radical de los lenguajes existentes, el más importante de los cuales era Fortran.

Lisp encarnaba nueve ideas nuevas:

1. Condicionales. Un condicional es una construcción de tipo if-then-else. Ahora los damos por sentados. Fueron inventados por McCarthy en el curso del desarrollo de Lisp. (Fortran en ese momento solo tenía un condicional goto, basado de cerca en la instrucción de ramificación en el hardware subyacente). McCarthy, que formaba parte del comité de Algol, consiguió que los condicionales se incluyeran en Algol, desde donde se extendieron a la mayoría de los otros lenguajes.

2. Un tipo de función. En Lisp, las funciones son objetos de primera clase -- son un tipo de datos al igual que los enteros, las cadenas, etc., y tienen una representación literal, se pueden almacenar en variables, se pueden pasar como argumentos, y así sucesivamente.

3. Recursión. La recursión existía como un concepto matemático antes que Lisp, por supuesto, pero Lisp fue el primer lenguaje de programación en admitir ella. (Se podría decir que es implícita en hacer que las funciones sean objetos de primera clase).

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 vincular variables significa copiar punteros, no lo que apuntan.

5. Recolección de basura.

6. Programas compuestos de expresiones. Los programas Lisp son árboles de expresiones, cada una de las cuales devuelve un valor. (En algunos Lisps, las expresiones pueden devolver varios valores). Esto contrasta con Fortran y la mayoría de los lenguajes sucesivos, que distinguen entre expresiones y declaraciones.

Era natural tener esta distinción en Fortran porque (no sorprendentemente 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 por lo tanto, si bien necesitabas expresiones para que las matemáticas funcionaran, no había ningún punto en hacer que cualquier otra cosa devolviera un valor, porque no podía haber nada esperándolo.

Esta limitación desapareció con la llegada de los lenguajes de estructura de bloques, pero para entonces ya era demasiado tarde. La distinción entre expresiones y declaraciones se había arraigado. Se extendió de Fortran a Algol y de ahí a sus descendientes.

Cuando un lenguaje se compone enteramente de expresiones, puedes componer expresiones como quieras. Puedes decir tanto (usando Arc sintaxis)

(if foo (= x 1) (= x 2))

como

(= x (if foo 1 2))

7. Un tipo de símbolo. Los símbolos se diferencian 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 se compila, 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 los 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 muy alejadas de la práctica de programación habitual, 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 son generalizados. 6 está empezando a aparecer en el mainstream. Python tiene una forma de 7, aunque no parece haber ninguna sintaxis para ello. 8, que (con 9) es lo que hace posibles los macros de Lisp, sigue siendo único de Lisp, quizás porque (a) requiere esos paréntesis, o algo igual de malo, y (b) si añades ese último incremento de poder, ya no puedes afirmar 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 con respecto a los expedientes aleatorios que otros lenguajes adoptaron. Probablemente, no era así como McCarthy lo concebía. Lisp no se diseñó para corregir los errores en Fortran; surgió más bien como un subproducto de un intento de axiomatizar el cálculo.