El Lenguaje de los Cien Años

Abril de 2003

(Este ensayo se deriva de una charla magistral en PyCon 2003.)

Es difícil predecir cómo será la vida dentro de cien años. Solo hay unas pocas cosas que podemos decir con certeza. Sabemos que todos conducirán coches voladores, que las leyes de zonificación se relajarán para permitir edificios de cientos de pisos de altura, que estará oscuro la mayor parte del tiempo y que las mujeres estarán entrenadas en artes marciales. Aquí quiero centrarme en un detalle de esta imagen. ¿Qué tipo de lenguaje de programación usarán para escribir el software que controle esos coches voladores?

Esto vale la pena pensarlo no tanto porque vayamos a usar realmente estos lenguajes, sino porque, si tenemos suerte, usaremos lenguajes en el camino desde este punto hasta ese.

Creo que, al igual que las especies, los lenguajes formarán árboles evolutivos, con callejones sin salida que se ramificarán por todas partes. Ya podemos ver que esto sucede. Cobol, a pesar de su popularidad en su momento, no parece tener descendientes intelectuales. Es un callejón sin salida evolutivo, un lenguaje neandertal.

Predigo un destino similar para Java. La gente a veces me envía correos diciendo: "¿Cómo puedes decir que Java no resultará ser un lenguaje exitoso? ¡Ya es un lenguaje exitoso!". Y admito que lo es, si mides el éxito por el espacio en los estantes ocupado por libros sobre él (particularmente libros individuales sobre él), o por el número de estudiantes universitarios que creen que tienen que aprenderlo para conseguir un trabajo. Cuando digo que Java no resultará ser un lenguaje exitoso, me refiero a algo más específico: que Java resultará ser un callejón sin salida evolutivo, como Cobol.

Esto es solo una suposición. Puede que me equivoque. Mi punto aquí no es criticar a Java, sino plantear la cuestión de los árboles evolutivos y hacer que la gente pregunte: ¿dónde está el lenguaje X en el árbol? La razón para hacer esta pregunta no es solo para que nuestros fantasmas puedan decir, dentro de cien años, ya se los dije. Es porque mantenerse cerca de las ramas principales es una heurística útil para encontrar lenguajes en los que será bueno programar ahora.

En cualquier momento dado, probablemente estarás más feliz en las ramas principales de un árbol evolutivo. Incluso cuando todavía había muchos neandertales, debe haber sido horrible ser uno. Los cromañones te habrían estado golpeando constantemente y robándote la comida.

La razón por la que quiero saber cómo serán los lenguajes dentro de cien años es para saber en qué rama del árbol apostar ahora.

La evolución de los lenguajes difiere de la evolución de las especies porque las ramas pueden converger. La rama de Fortran, por ejemplo, parece fusionarse con los descendientes de Algol. En teoría, esto es posible para las especies también, pero es poco probable que haya sucedido a algo más grande que una célula.

La convergencia es más probable para los lenguajes en parte porque el espacio de posibilidades es menor, y en parte porque las mutaciones no son aleatorias. Los diseñadores de lenguajes incorporan deliberadamente ideas de otros lenguajes.

Es especialmente útil para los diseñadores de lenguajes pensar hacia dónde es probable que conduzca la evolución de los lenguajes de programación, porque pueden dirigirse en consecuencia. En ese caso, "mantenerse en una rama principal" se convierte en algo más que una forma de elegir un buen lenguaje. Se convierte en una heurística para tomar las decisiones correctas sobre el diseño del lenguaje.

Cualquier lenguaje de programación se puede dividir en dos partes: un conjunto de operadores fundamentales que desempeñan el papel de axiomas, y el resto del lenguaje, que en principio podría escribirse en términos de estos operadores fundamentales.

Creo que los operadores fundamentales son el factor más importante en la supervivencia a largo plazo de un lenguaje. El resto se puede cambiar. Es como la regla de que al comprar una casa, primero debes considerar la ubicación. Todo lo demás lo puedes arreglar después, pero no puedes arreglar la ubicación.

Creo que es importante no solo que los axiomas estén bien elegidos, sino que haya pocos de ellos. Los matemáticos siempre han pensado así sobre los axiomas: cuantos menos, mejor, y creo que tienen razón.

Como mínimo, tiene que ser un ejercicio útil examinar de cerca el núcleo de un lenguaje para ver si hay algún axioma que se pueda eliminar. He descubierto en mi larga carrera como vago que la suciedad engendra suciedad, y he visto que esto sucede tanto en el software como debajo de las camas y en las esquinas de las habitaciones.

Tengo la corazonada de que las ramas principales del árbol evolutivo pasan por los lenguajes que tienen los núcleos más pequeños y limpios. Cuanto más de un lenguaje puedas escribir en sí mismo, mejor.

Por supuesto, estoy haciendo una gran suposición al preguntar siquiera cómo serán los lenguajes de programación dentro de cien años. ¿Seguiremos escribiendo programas dentro de cien años? ¿No les diremos simplemente a las computadoras lo que queremos que hagan?

No ha habido mucho progreso en ese departamento hasta ahora. Mi suposición es que dentro de cien años la gente seguirá diciendo a las computadoras qué hacer usando programas que reconoceríamos como tales. Puede haber tareas que resolvamos ahora escribiendo programas y que dentro de cien años no tendrás que escribir programas para resolver, pero creo que todavía habrá una buena cantidad de programación del tipo que hacemos hoy.

Puede parecer presuntuoso pensar que alguien puede predecir cómo será cualquier tecnología dentro de cien años. Pero recuerde que ya tenemos casi cincuenta años de historia a nuestras espaldas. Mirar cien años hacia adelante es una idea comprensible cuando consideramos cuán lentamente han evolucionado los lenguajes en los últimos cincuenta años.

Los lenguajes evolucionan lentamente porque en realidad no son tecnologías. Los lenguajes son notación. Un programa es una descripción formal del problema que quieres que una computadora resuelva por ti. Por lo tanto, la tasa de evolución en los lenguajes de programación se parece más a la tasa de evolución en la notación matemática que, por ejemplo, al transporte o las comunicaciones. La notación matemática evoluciona, pero no con los saltos gigantes que ves en la tecnología.

Sea lo que sea de lo que estén hechas las computadoras dentro de cien años, parece seguro predecir que serán mucho más rápidas que ahora. Si la Ley de Moore continúa produciendo, serán 74 quintillones (73.786.976.294.838.206.464) de veces más rápidas. Eso es difícil de imaginar. Y, de hecho, la predicción más probable en el departamento de velocidad puede ser que la Ley de Moore deje de funcionar. Cualquier cosa que se suponga que se duplica cada dieciocho meses parece probable que eventualmente se encuentre con algún tipo de límite fundamental. Pero no tengo problemas en creer que las computadoras serán mucho más rápidas. Incluso si solo terminan siendo unas patéticas un millón de veces más rápidas, eso debería cambiar sustancialmente las reglas del juego para los lenguajes de programación. Entre otras cosas, habrá más espacio para lo que ahora se consideraría lenguajes lentos, es decir, lenguajes que no producen código muy eficiente.

Y, sin embargo, algunas aplicaciones seguirán exigiendo velocidad. Algunos de los problemas que queremos resolver con las computadoras son creados por las computadoras; por ejemplo, la velocidad a la que tienes que procesar imágenes de video depende de la velocidad a la que otra computadora puede generarlas. Y hay otra clase de problemas que inherentemente tienen una capacidad ilimitada para absorber ciclos: renderizado de imágenes, criptografía, simulaciones.

Si algunas aplicaciones pueden ser cada vez más ineficientes mientras que otras continúan exigiendo toda la velocidad que el hardware puede entregar, las computadoras más rápidas significarán que los lenguajes tendrán que cubrir un rango de eficiencias cada vez mayor. Ya hemos visto que esto sucede. Las implementaciones actuales de algunos lenguajes nuevos y populares son sorprendentemente derrochadoras según los estándares de décadas anteriores.

Esto no es solo algo que sucede con los lenguajes de programación. Es una tendencia histórica general. A medida que las tecnologías mejoran, cada generación puede hacer cosas que la generación anterior habría considerado derrochadoras. Las personas de hace treinta años se asombrarían de la naturalidad con la que hacemos llamadas telefónicas de larga distancia. Las personas de hace cien años se asombrarían aún más de que un paquete viajara algún día de Boston a Nueva York vía Memphis.

Ya puedo decirles qué sucederá con todos esos ciclos adicionales que el hardware más rápido nos proporcionará en los próximos cien años. Casi todos se desperdiciarán.

Aprendí a programar cuando el poder de las computadoras era escaso. Recuerdo haber quitado todos los espacios de mis programas Basic para que cupieran en la memoria de un TRS-80 de 4K. La idea de todo este software estupendamente ineficiente quemando ciclos haciendo lo mismo una y otra vez me parece algo asqueroso. Pero creo que mis intuiciones aquí están equivocadas. Soy como alguien que creció pobre y no soporta gastar dinero, ni siquiera en algo importante, como ir al médico.

Algunos tipos de desperdicio son realmente asquerosos. Los SUV, por ejemplo, serían discutiblemente asquerosos incluso si funcionaran con un combustible que nunca se agotara y no generaran contaminación. Los SUV son asquerosos porque son la solución a un problema asqueroso. (¿Cómo hacer que las minivans parezcan más masculinas?). Pero no todo desperdicio es malo. Ahora que tenemos la infraestructura para soportarlo, contar los minutos de tus llamadas de larga distancia parece mezquino. Si tienes los recursos, es más elegante pensar en todas las llamadas telefónicas como un solo tipo de cosa, sin importar dónde esté la otra persona.

Hay desperdicio bueno y desperdicio malo. Estoy interesado en el desperdicio bueno: el tipo en el que, gastando más, podemos obtener diseños más simples. ¿Cómo aprovecharemos las oportunidades para desperdiciar ciclos que obtendremos del hardware nuevo y más rápido?

El deseo de velocidad está tan profundamente arraigado en nosotros, con nuestras computadoras diminutas, que se necesitará un esfuerzo consciente para superarlo. En el diseño de lenguajes, deberíamos buscar conscientemente situaciones en las que podamos intercambiar eficiencia por un aumento, por pequeño que sea, en la conveniencia.

La mayoría de las estructuras de datos existen por la velocidad. Por ejemplo, muchos lenguajes hoy en día tienen tanto cadenas como listas. Semánticamente, las cadenas son más o menos un subconjunto de listas en las que los elementos son caracteres. Entonces, ¿por qué necesitas un tipo de dato separado? Realmente no. Las cadenas solo existen por eficiencia. Pero es lamentable saturar la semántica del lenguaje con trucos para que los programas se ejecuten más rápido. Tener cadenas en un lenguaje parece ser un caso de optimización prematura.

Si pensamos en el núcleo de un lenguaje como un conjunto de axiomas, ciertamente es asqueroso tener axiomas adicionales que no añaden poder expresivo, simplemente por el bien de la eficiencia. La eficiencia es importante, pero no creo que esa sea la forma correcta de conseguirla.

La forma correcta de resolver ese problema, creo, es separar el significado de un programa de los detalles de implementación. En lugar de tener tanto listas como cadenas, solo ten listas, con alguna forma de dar al compilador consejos de optimización que le permitan organizar las cadenas como bytes contiguos si es necesario.

Dado que la velocidad no importa en la mayor parte de un programa, normalmente no necesitarás preocuparte por este tipo de microgestión. Esto será cada vez más cierto a medida que las computadoras se vuelvan más rápidas.

Decir menos sobre la implementación también debería hacer que los programas sean más flexibles. Las especificaciones cambian mientras se escribe un programa, y esto no solo es inevitable, sino deseable.

La palabra "ensayo" proviene del verbo francés "essayer", que significa "intentar". Un ensayo, en el sentido original, es algo que escribes para intentar descifrar algo. Esto también sucede en el software. Creo que algunos de los mejores programas fueron ensayos, en el sentido de que los autores no sabían cuando empezaron exactamente lo que estaban intentando escribir.

Los hackers de Lisp ya saben el valor de ser flexibles con las estructuras de datos. Tendemos a escribir la primera versión de un programa de manera que haga todo con listas. Estas versiones iniciales pueden ser tan ineficientes que se necesita un esfuerzo consciente para no pensar en lo que están haciendo, al igual que, al menos para mí, comer un filete requiere un esfuerzo consciente para no pensar de dónde viene.

Lo que los programadores dentro de cien años buscarán, sobre todo, es un lenguaje donde puedas juntar una versión 1 de un programa increíblemente ineficiente con el menor esfuerzo posible. Al menos, así es como lo describiríamos en términos actuales. Lo que dirán es que quieren un lenguaje en el que sea fácil programar.

El software ineficiente no es asqueroso. Lo que es asqueroso es un lenguaje que hace que los programadores hagan trabajo innecesario. Desperdiciar tiempo de programador es la verdadera ineficiencia, no desperdiciar tiempo de máquina. Esto será cada vez más claro a medida que las computadoras se vuelvan más rápidas.

Creo que deshacernos de las cadenas ya es algo que podríamos considerar. Lo hicimos en Arc, y parece ser una victoria; algunas operaciones que serían difíciles de describir como expresiones regulares se pueden describir fácilmente como funciones recursivas.

¿Hasta dónde llegará este aplanamiento de las estructuras de datos? Puedo pensar en posibilidades que me sorprenden incluso a mí, con mi mente conscientemente ampliada. ¿Nos desharemos de los arrays, por ejemplo? Después de todo, son solo un subconjunto de las tablas hash donde las claves son vectores de enteros. ¿Reemplazaremos las tablas hash mismas con listas?

Hay perspectivas aún más impactantes. El Lisp que McCarthy describió en 1960, por ejemplo, no tenía números. Lógicamente, no necesitas tener una noción separada de números, porque puedes representarlos como listas: el entero n podría representarse como una lista de n elementos. Puedes hacer matemáticas de esta manera. Es simplemente insoportablemente ineficiente.

Nadie propuso realmente implementar números como listas en la práctica. De hecho, el artículo de McCarthy de 1960 no estaba, en ese momento, destinado a ser implementado en absoluto. Era un ejercicio teórico, un intento de crear una alternativa más elegante a la Máquina de Turing. Cuando alguien, inesperadamente, tomó este artículo y lo tradujo a un intérprete Lisp funcional, los números ciertamente no se representaban como listas; se representaban en binario, como en todos los demás lenguajes.

¿Podría un lenguaje de programación llegar tan lejos como para eliminar los números como tipo de dato fundamental? Pregunto esto no tanto como una pregunta seria, sino como una forma de jugar al gallito con el futuro. Es como el caso hipotético de una fuerza irresistible que se encuentra con un objeto inamovible: aquí, una implementación inimaginablemente ineficiente que se encuentra con recursos inimaginablemente grandes. No veo por qué no. El futuro es bastante largo. Si hay algo que podamos hacer para disminuir el número de axiomas en el lenguaje principal, ese parecería ser el lado en el que apostar a medida que t tiende a infinito. Si la idea todavía parece insoportable dentro de cien años, tal vez no lo sea en mil.

Solo para aclarar esto, no propongo que todos los cálculos numéricos se realicen realmente utilizando listas. Propongo que el lenguaje principal, antes de cualquier notación adicional sobre la implementación, se defina de esta manera. En la práctica, cualquier programa que quisiera hacer una cantidad de matemáticas probablemente representaría los números en binario, pero esto sería una optimización, no parte de la semántica del lenguaje principal.

Otra forma de quemar ciclos es tener muchas capas de software entre la aplicación y el hardware. Esta también es una tendencia que vemos suceder ya: muchos lenguajes recientes se compilan en bytecode. Bill Woods me dijo una vez que, como regla general, cada capa de interpretación cuesta un factor de 10 en velocidad. Este costo adicional te da flexibilidad.

La primera versión de Arc fue un caso extremo de este tipo de lentitud multinivel, con beneficios correspondientes. Fue un intérprete "metacircular" clásico escrito sobre Common Lisp, con un parecido familiar definido con la función eval definida en el artículo original de Lisp de McCarthy. Todo el asunto tenía solo un par de cientos de líneas de código, por lo que era muy fácil de entender y cambiar. El Common Lisp que usamos, CLisp, se ejecuta a su vez sobre un intérprete de bytecode. Así que aquí teníamos dos niveles de interpretación, uno de ellos (el superior) sorprendentemente ineficiente, y el lenguaje era utilizable. Apenas utilizable, lo admito, pero utilizable.

Escribir software como múltiples capas es una técnica poderosa incluso dentro de las aplicaciones. La programación de abajo hacia arriba significa escribir un programa como una serie de capas, cada una de las cuales sirve como lenguaje para la de arriba. Este enfoque tiende a producir programas más pequeños y flexibles. También es la mejor ruta hacia ese santo grial, la reutilización. Un lenguaje es por definición reutilizable. Cuanto más de tu aplicación puedas empujar hacia un lenguaje para escribir ese tipo de aplicación, más de tu software será reutilizable.

De alguna manera, la idea de reutilización se asoció con la programación orientada a objetos en la década de 1980, y ninguna cantidad de evidencia en contrario parece poder sacudírsela. Pero aunque parte del software orientado a objetos es reutilizable, lo que lo hace reutilizable es su enfoque de abajo hacia arriba, no su orientación a objetos. Considere las bibliotecas: son reutilizables porque son lenguajes, ya sea que estén escritos en un estilo orientado a objetos o no.

Por cierto, no predigo la desaparición de la programación orientada a objetos. Aunque no creo que tenga mucho que ofrecer a los buenos programadores, excepto en ciertos dominios especializados, es irresistible para las grandes organizaciones. La programación orientada a objetos ofrece una forma sostenible de escribir código espagueti. Te permite acumular programas como una serie de parches. Las grandes organizaciones siempre tienden a desarrollar software de esta manera, y espero que esto sea tan cierto dentro de cien años como lo es hoy.

Ya que estamos hablando del futuro, será mejor que hablemos de computación paralela, porque ahí es donde parece vivir esta idea. Es decir, no importa cuándo hables, la computación paralela parece ser algo que va a suceder en el futuro.

¿El futuro alguna vez lo alcanzará? La gente ha estado hablando de la computación paralela como algo inminente durante al menos 20 años, y hasta ahora no ha afectado mucho la práctica de la programación. ¿O no lo ha hecho? Los diseñadores de chips ya tienen que pensar en ello, y también las personas que intentan escribir software de sistemas en computadoras con múltiples CPU.

La verdadera pregunta es, ¿hasta dónde llegará el paralelismo en la escala de abstracción? ¿Dentro de cien años afectará incluso a los programadores de aplicaciones? ¿O será algo en lo que piensen los escritores de compiladores, pero que generalmente sea invisible en el código fuente de las aplicaciones?

Una cosa que sí parece probable es que la mayoría de las oportunidades de paralelismo se desperdicien. Este es un caso especial de mi predicción más general de que la mayor parte del poder informático adicional que se nos da se desperdiciará. Espero que, al igual que con la velocidad estupenda del hardware subyacente, el paralelismo sea algo que esté disponible si lo pides explícitamente, pero que normalmente no se use. Esto implica que el tipo de paralelismo que tendremos dentro de cien años no será, excepto en aplicaciones especiales, paralelismo masivo. Espero que para los programadores comunes sea más como poder lanzar procesos que terminen ejecutándose en paralelo.

Y esto, al igual que pedir implementaciones específicas de estructuras de datos, será algo que harás bastante tarde en la vida de un programa, cuando intentes optimizarlo. Las versiones 1 generalmente ignorarán cualquier ventaja que se pueda obtener de la computación paralela, al igual que ignorarán las ventajas que se pueden obtener de representaciones específicas de datos.

Excepto en tipos especiales de aplicaciones, el paralelismo no impregnará los programas que se escriban dentro de cien años. Sería una optimización prematura si lo hiciera.

¿Cuántos lenguajes de programación habrá dentro de cien años? Parece haber un gran número de nuevos lenguajes de programación últimamente. Parte de la razón es que el hardware más rápido ha permitido a los programadores hacer diferentes intercambios entre velocidad y conveniencia, dependiendo de la aplicación. Si esta es una tendencia real, el hardware que tendremos dentro de cien años solo debería aumentarla.

Y, sin embargo, puede que solo haya unos pocos lenguajes de uso generalizado dentro de cien años. Parte de la razón por la que digo esto es optimismo: parece que, si hicieras un trabajo realmente bueno, podrías crear un lenguaje que fuera ideal para escribir una versión 1 lenta, y aun así, con los consejos de optimización adecuados para el compilador, también produciría código muy rápido cuando fuera necesario. Por lo tanto, como soy optimista, predeciré que a pesar de la enorme brecha que tendrán entre la eficiencia aceptable y la máxima, los programadores dentro de cien años tendrán lenguajes que podrán abarcar la mayor parte de ella.

A medida que esta brecha se amplíe, los profilers serán cada vez más importantes. Actualmente se presta poca atención a la creación de perfiles. Muchas personas todavía parecen creer que la forma de obtener aplicaciones rápidas es escribir compiladores que generen código rápido. A medida que la brecha entre el rendimiento aceptable y el máximo se amplíe, quedará cada vez más claro que la forma de obtener aplicaciones rápidas es tener una buena guía de una a otra.

Cuando digo que puede haber solo unos pocos lenguajes, no incluyo "pequeños lenguajes" específicos de dominio. Creo que tales lenguajes integrados son una gran idea, y espero que proliferen. Pero espero que se escriban como capas lo suficientemente delgadas como para que los usuarios puedan ver el lenguaje de propósito general debajo.

¿Quién diseñará los lenguajes del futuro? Una de las tendencias más emocionantes de los últimos diez años ha sido el auge de los lenguajes de código abierto como Perl, Python y Ruby. El diseño de lenguajes está siendo asumido por hackers. Los resultados hasta ahora son desordenados, pero alentadores. Hay algunas ideas asombrosamente novedosas en Perl, por ejemplo. Muchas son asombrosamente malas, pero eso siempre ocurre con los esfuerzos ambiciosos. A su ritmo actual de mutación, Dios sabe en qué podría evolucionar Perl dentro de cien años.

No es cierto que los que no pueden hacer, enseñan (algunos de los mejores hackers que conozco son profesores), pero es cierto que hay muchas cosas que los que enseñan no pueden hacer. La investigación impone restricciones de casta restrictivas. En cualquier campo académico hay temas sobre los que está bien trabajar y otros que no. Desafortunadamente, la distinción entre temas aceptables y prohibidos generalmente se basa en cuán intelectual suena el trabajo cuando se describe en artículos de investigación, en lugar de cuán importante es para obtener buenos resultados. El caso extremo es probablemente la literatura; las personas que estudian literatura rara vez dicen algo que sea de la menor utilidad para quienes la producen.

Aunque la situación es mejor en las ciencias, la superposición entre el tipo de trabajo que se permite hacer y el tipo de trabajo que produce buenos lenguajes es descorazonadoramente pequeña. (Olin Shivers se ha quejado elocuentemente de esto). Por ejemplo, los tipos parecen ser una fuente inagotable de artículos de investigación, a pesar de que el tipado estático parece excluir los macros verdaderos, sin los cuales, en mi opinión, ningún lenguaje vale la pena usar.

La tendencia no es solo hacia que los lenguajes se desarrollen como proyectos de código abierto en lugar de "investigación", sino hacia que los lenguajes sean diseñados por los programadores de aplicaciones que necesitan usarlos, en lugar de por los escritores de compiladores. Esta parece ser una buena tendencia y espero que continúe.

A diferencia de la física dentro de cien años, que es casi necesariamente imposible de predecir, creo que puede ser posible en principio diseñar ahora un lenguaje que atraiga a los usuarios dentro de cien años.

Una forma de diseñar un lenguaje es simplemente escribir el programa que te gustaría poder escribir, independientemente de si hay un compilador que pueda traducirlo o hardware que pueda ejecutarlo. Cuando haces esto, puedes asumir recursos ilimitados. Parece que deberíamos ser capaces de imaginar recursos ilimitados hoy tanto como dentro de cien años.

¿Qué programa le gustaría escribir a uno? Lo que sea que requiera menos trabajo. Excepto que no del todo: lo que requeriría menos trabajo si tus ideas sobre programación no estuvieran ya influenciadas por los lenguajes a los que estás acostumbrado. Tal influencia puede ser tan generalizada que se necesita un gran esfuerzo para superarla. Pensarías que sería obvio para criaturas tan perezosas como nosotros cómo expresar un programa con el menor esfuerzo. De hecho, nuestras ideas sobre lo que es posible tienden a estar tan limitadas por el lenguaje que sea en el que pensemos que formulaciones más fáciles de programas parecen muy sorprendentes. Son algo que tienes que descubrir, no algo en lo que te hundes naturalmente.

Un truco útil aquí es usar la longitud del programa como una aproximación de cuánto trabajo cuesta escribirlo. No la longitud en caracteres, por supuesto, sino la longitud en elementos sintácticos distintos: básicamente, el tamaño del árbol de análisis. Puede que no sea del todo cierto que el programa más corto sea el que menos trabajo cuesta escribir, pero está lo suficientemente cerca como para que sea mejor apuntar al objetivo sólido de la brevedad que al objetivo difuso y cercano del menor trabajo. Entonces, el algoritmo para el diseño de lenguajes se convierte en: mira un programa y pregunta, ¿hay alguna forma de escribir esto que sea más corta?

En la práctica, escribir programas en un lenguaje imaginario de cien años funcionará en diversos grados dependiendo de cuán cerca estés del núcleo. Las rutinas de ordenación se pueden escribir ahora. Pero sería difícil predecir ahora qué tipo de bibliotecas podrían ser necesarias dentro de cien años. Presumiblemente, muchas bibliotecas serán para dominios que aún no existen. Si SETI@home funciona, por ejemplo, necesitaremos bibliotecas para comunicarnos con extraterrestres. A menos, por supuesto, que sean lo suficientemente avanzados como para que ya se comuniquen en XML.

En el otro extremo, creo que podrías diseñar el lenguaje principal hoy mismo. De hecho, algunos podrían argumentar que ya estaba mayormente diseñado en 1958.

Si el lenguaje de cien años estuviera disponible hoy, ¿querríamos programar en él? Una forma de responder a esta pregunta es mirar hacia atrás. Si los lenguajes de programación actuales hubieran estado disponibles en 1960, ¿habría querido alguien usarlos?

En algunos aspectos, la respuesta es no. Los lenguajes actuales asumen una infraestructura que no existía en 1960. Por ejemplo, un lenguaje en el que la indentación es significativa, como Python, no funcionaría muy bien en terminales de impresión. Pero dejando de lado tales problemas, asumiendo, por ejemplo, que todos los programas se escribieran en papel, ¿les habría gustado a los programadores de la década de 1960 escribir programas en los lenguajes que usamos ahora?

Creo que sí. Algunos de los menos imaginativos, que tenían artefactos de lenguajes tempranos incorporados en sus ideas sobre lo que era un programa, podrían haber tenido problemas. (¿Cómo se puede manipular datos sin hacer aritmética de punteros? ¿Cómo se pueden implementar diagramas de flujo sin gotos?) Pero creo que los programadores más inteligentes no habrían tenido problemas para sacar el máximo provecho de los lenguajes actuales, si los hubieran tenido.

Si tuviéramos el lenguaje de cien años ahora, al menos serviría como un gran pseudocódigo. ¿Qué hay de usarlo para escribir software? Dado que el lenguaje de cien años necesitará generar código rápido para algunas aplicaciones, presumiblemente podría generar código lo suficientemente eficiente como para ejecutarse de manera aceptable en nuestro hardware. Es posible que tengamos que dar más consejos de optimización que los usuarios dentro de cien años, pero aún así podría ser una ganancia neta.

Ahora tenemos dos ideas que, si las combinamos, sugieren posibilidades interesantes: (1) el lenguaje de cien años podría, en principio, diseñarse hoy, y (2) tal lenguaje, si existiera, podría ser bueno para programar hoy. Cuando ves estas ideas presentadas así, es difícil no pensar, ¿por qué no intentar escribir el lenguaje de cien años ahora?

Cuando trabajas en el diseño de lenguajes, creo que es bueno tener un objetivo así y mantenerlo conscientemente en mente. Cuando aprendes a conducir, uno de los principios que te enseñan es alinear el coche no alineando el capó con las rayas pintadas en la carretera, sino apuntando a algún punto en la distancia. Incluso si lo único que te importa es lo que sucede en los próximos diez pies, esta es la respuesta correcta. Creo que podemos y debemos hacer lo mismo con los lenguajes de programación.

Notas

Creo que Lisp Machine Lisp fue el primer lenguaje en incorporar el principio de que las declaraciones (excepto las de variables dinámicas) eran meros consejos de optimización, y no cambiarían el significado de un programa correcto. Common Lisp parece haber sido el primero en declararlo explícitamente.

Gracias a Trevor Blackwell, Robert Morris y Dan Giffin por leer borradores de esto, y a Guido van Rossum, Jeremy Hylton y el resto del equipo de Python por invitarme a hablar en PyCon.