Scheme se muere. Larga vida, Clojure, Racket, Common Lisp y Lua.

Para hacer pequeños experimentos y prototipar cosillas suelo usar un lenguaje de programación que sea lo más sencillo posible. Uno de los más sencillos, y de los más potentes, es Scheme. Uno necesita un editor de texto, una línea de comandos y un pequeño ejecutable de unos cuantos kilobytes y a correr. Ideal para situaciones de emergencia que requieran una solución rápida.

A pesar de que Scheme me gusta mucho el problema es que los intérpretes de Scheme son o demasiado pobres (uno no puede hacer una conexión de red, por ejemplo) o si tienen lo que a uno le hace falta (las funciones para acceder a la red) entonces lo que hace no es portable. Y, claro, a veces los prototipos se convierten en cosas útiles que conviene guardar.

Allá en mayo de 2010 comentaba que iba a elegir un lenguaje de programación alternativo a Scheme, que me permitiese solventar estos problemas. Cuatro años más tarde el nuevo estándar, el R7RS no me gusta nada. El lenguaje sigue sin tener estructuras de datos potentes (diccionarios o estructuras, por ejemplo) y no soporta hilos de ejecución, o concurrencia. El nuevo estándar ha incluido cosas que no necesito, y Scheme continúa fuera de juego para mis necesidades.

Lua

En aquella entrada de mayo de 2010 comentaba que iba a usar Lua como lenguaje para la experimentación (con Clojure como firme candidato). Y la verdad es que es un lenguaje muy útil para prototipar cosas, se integra relativamente bien con C y me permite hacer experimentos rápidamente (estas páginas web, por ejemplo, no son más que programas Lua).

Y más allá

Resulta que estos días estoy leyendo el Clojure Programming de Chas Emerick, que es excelente. Y cuánto más leo sobre Clojure más útil me parece (creo que Clojure es una gran colección de ideas inteligentes), y más limitaciones le veo a Lua.

Conforme uno se hace viejo se va desprendiendo de fanatismos y tonterías sobre el software (y, de paso, de pelo, pero se provee de barriga y reúma, para compensar), y elige el software de forma fría y calculadora.

Pues eso, he pensado que voy a elegir un nuevo lenguaje de programación para mis prototipos, y lo voy a hacer públicamente y de forma fría y calculadora.

El objetivo es darle algo de vidilla al blog, que está algo rancio, y de paso mostrar los criterios de selección que uso por si alguien puede sugerir alternativas, correcciones o sugerencias (de forma fría y calculadora también, por favor).

Los criterios

Los criterios para el nuevo lenguaje de prototipado son éstos:

  1. El lenguaje debe ser relativamente pequeño. Del tamaño de Lua sería ideal. Que funcione en Mac OS/X y FreeBSD, y opcionalmente en Windows.
  2. El lenguaje debe poder ampliarse a voluntad, de modo que uno pueda hacer peticiones HTTP o leer un documento XML sin tener que hacerse un stack de red o un parser de XML. Con todo que sea fácil de instalar: no quiero tener que bajarme de Internet todo el mundo y parte del extranjero.
  3. La sintaxis debería ser homoicónica, porque es útil que un programa sea un dato, por si hay que hacer programas que hagan programas.
  4. Ya puestos podría tener macros, para hacer más programas con programas y de paso empeorar la legibilidad del código a costa de evitar repetirse.
  5. Debería ser portable, y preferiblemente que sea estándar. De modo que funcione en la mayor variedad posible de plataformas: desde pequeños aparatos a grandes servidores. Sin líos de implementaciones y otros problemas innecesarios y evitables.
  6. Debería soportar algún sistema de concurrencia, para aprovechar esos "core" de los microprocesadores "multicore" que tengo, y que tanto me han costado.
  7. Debería soportar recursividad final, total o parcialmente, porque cuando hago funciones recursivas en Java siempre me queda la preocupación de si tendré o no un "StackOverflow". Es como una bomba de relojería que puede estallar en cualquier momento.
  8. Debería soportar funciones de primera clase, porque es útil usar clausuras de vez en cuando, y pasarse funciones para parametrizar algoritmos.
  9. Debería tener estructuras de datos útiles: diccionarios, conjuntos, listas y "arrays" son suficientes. Y tipos de datos relativamente sencillos: números y cadenas de caracteres son suficientes.
  10. Y que se pueda acceder a librerías en C de forma sencilla. El acceso a Cairo, Pango, libxml2 y libxslt son cada vez más frecuentes.

Los candidatos

Una vez pensadas las preguntas para el examen pues busco a candidatos para ver qué nota tienen. Por el requisito 3 (homoiconicidad) elijo estos candidatos:

Iba a poner también newLISP y el arc pero es que no vale la pena, creo.

Las notas

Una vez las preguntas y los candidatos viene la hora de la evaluación. Las notas son -1 para los puntos negativos, 0 si la cosa no está clara y +1 si el candidato aprueba con nota.

Los resultados que han obtanido, salvo error u omisión, son los siguientes:

RequisitoClojureCommon LispRacketLua
1. Pequeño -1 1 (ECL) 0 1
2. Ampliable 1 1 1 1
3. Homoicónico 1 1 1 -1
4. Macros 1 1 1 -1
5. Portable 0 (JVM) 1 1 1
6. Multicore 1 1 1 -1
7. Recursivo final 1 1 1 1
8. Funciones 1ª clase 1 1 1 1
9. Estructuras 1 1 1 0
10. Acceso a C 1 1 1 1
TOTAL 7 10 9 3

Con lo que el ganador es Common Lisp, con firmes candidatos racket-lang y clojure, en ese orden. Ése será el nuevo lenguaje de prototipado.

Racket ha estado a puntito de aprobar, con un punto de diferencia sobre Common Lisp, y no lo supera por su tamaño. Es una pena, porque me gustaría experimentar con PLT Redex, una extensión a racket para evaluar semánticas operacionales y experimentar con hacer nuevos lenguajes de programación.

Clojure se queda atrás por lo voluminoso que es (el requisito 1 con puntuación -1) y por que no es tan portable como el resto, en tanto en cuanto requiere una máquina virtual Java para funcionar, y no siempre tengo una a mano. De hecho sí hay una versión de Common Lisp que funciona en la máquina virtual por lo que los programas que haga en mi nuevo lenguaje de programación de prototipado podrán funcionar en la máquina virtual Java también.

El ganador, Common Lisp, es además estándar ANSI, lo que lo hace todavía más interesante.

Pues eso, "Scheme is dead, long life Common Lisp!"