Loading...

EL LENGUAJE DE CIEN AÑOS

Original

April 2003

(Este ensayo está derivado de una ponencia principal en PyCon 2003.)

Es difícil predecir cómo será la vida dentro de cien años. Sólo hay unas pocas cosas que podemos decir con seguridad. Sabemos que todo el mundo conducirá 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 todas las mujeres estarán entrenadas en artes marciales. Aquí quiero hacer zoom en un detalle de este cuadro. ¿Qué tipo de lenguaje de programación usarán para escribir el software que controla esos coches voladores?

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

Creo que, al igual que las especies, los lenguajes formarán árboles evolutivos, con callejones sin salida ramificándose por todas partes. Podemos ver esto sucediendo ya. Cobol, a pesar de su alguna vez popularidad, 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 correo electrónico diciendo: "Cómo puedes decir que Java no va a ser un lenguaje exitoso? Ya es un lenguaje exitoso." Y admito que lo es, si medimos el éxito por el espacio en los estantes que ocupan los libros sobre él (en particular los 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 va a 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 sólo una suposición. Puede que esté equivocado. Mi punto aquí no es desprestigiar a Java, sino plantear el tema de los árboles evolutivos y hacer que la gente se 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, te lo dije. Es porque mantenerse cerca de las ramas principales es una heurística útil para encontrar lenguajes que serán buenos para programar ahora.

En un momento dado, probablemente seas más feliz en las ramas principales de un árbol evolutivo. Incluso cuando todavía había muchos neandertales, debe haber sido una porquería ser uno. El Cro-Magnon habría estado entrando constantemente y golpeándote 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 Fortran, por ejemplo, parece estar fusionándose con los descendientes de Algol. En teoría, esto también es posible para las especies, pero es poco probable que haya ocurrido con ninguna mayor 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 en dónde es probable que conduzca la evolución de los lenguajes de programación, porque pueden dirigirla en consecuencia. En ese caso, "mantenerse en una rama principal" se convierte en algo más que un modo 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 puede dividirse en dos partes: un conjunto de operadores fundamentales que juegan 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 puedes cambiarlo. Es como la regla de que al comprar una casa debes considerar la ubicación en primer lugar. Todo lo demás puedes arreglarlo más tarde, pero no puedes arreglar la ubicación.

Creo que es importante no sólo que los axiomas estén bien elegidos, sino que haya pocos de ellos. Los matemáticos siempre se han sentido de esta manera sobre los axiomas, cuantos menos, mejor, y creo que están en lo cierto.

Como mínimo, tiene que ser un ejercicio útil mirar de cerca el núcleo de un lenguaje para ver si hay algún axioma que pueda ser eliminado. He descubierto en mi larga carrera como holgazán que la porquería engendra porquería, y he visto que esto ocurre en el software tanto 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 lenguaje puedas escribir en sí mismo, mejor.

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

Hasta ahora no ha habido mucho progreso en ese departamento. Mi suposición es que dentro de cien años la gente seguirá diciéndole a las computadoras qué hacer usando programas que nosotros reconoceríamos como tales. Puede que haya tareas que resolvemos ahora escribiendo programas y que dentro de cien años no tengamos que escribir programas para resolver, pero creo que seguirá habiendo una buena parte 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 recuerda que ya tenemos casi cincuenta años de historia detrás. Mirar hacia delante cien años es una idea comprensible si consideramos lo lentamente que los lenguajes han evolucionado en el pasado medio siglo.

Los lenguajes evolucionan lentamente porque en realidad no son tecnologías. Los lenguajes son notación. Un programa es una descripción formal de el problema que quieres que una computadora resuelva por ti. Así que la tasa de evolución en los lenguajes de programación es más como la tasa de evolución en la notación matemática que, digamos, el transporte o las comunicaciones. La notación matemática sí evoluciona, pero no con los gigantescos saltos que se ven en la tecnología.

Cualquiera que sea el material de 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 sigue saliendo, serán 74 quintillones (73.786.976.294.838.206.464) veces más rápidas. Es algo 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 supone que debe duplicarse cada dieciocho meses parece probable que se tope con algún tipo de límite fundamental en algún momento. Pero no tengo problemas en creer que las computadoras serán mucho más rápidas. Incluso si sólo acaban siendo un millón de veces más rápidas, eso debería cambiar las reglas del juego para la programación de los lenguajes de forma sustancial. Entre otras cosas, habrá más espacio para lo que ahora se considera 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, el ritmo al que tienes que procesar imágenes de vídeo depende del ritmo al 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 siguen exigiendo toda la velocidad que el hardware puede proporcionar, las computadoras más rápidas significarán que los lenguajes tienen que cubrir un rango de eficiencias cada vez más amplio. Hemos visto que esto ya está sucediendo. Las implementaciones actuales de algunos lenguajes nuevos populares son sorprendentemente derrochadoras por los estándares de las décadas anteriores.

Esto no es algo que solo suceda con la programación de los lenguajes. Es una tendencia histórica general. A medida que las tecnologías mejoran, cada generación puede hacer cosas que la generación anterior hubiera considerado un derroche. Las personas de hace treinta años se asombrarían de lo casualmente 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 un día de Boston a Nueva York vía Memphis.

Ya puedo decirles qué va a pasar con todos esos ciclos extra que el hardware más rápido nos va a dar en el próximo siglo. Casi todos se van a desperdiciar.

Aprendí a programar cuando la potencia informática era escasa. Recuerdo quitar todos los espacios de mis programas Basic para que cupieran en la memoria de un TRS-80 de 4K. El pensamiento de todo este software estupendamente ineficiente quemando ciclos haciendo lo mismo una y otra vez parece algo repugnante para mí. Pero creo que mis intuiciones aquí están equivocadas. Soy como alguien que ha crecido pobre y no puede soportar gastar dinero ni siquiera en algo importante, como ir al médico.

Algunos tipos de desperdicio realmente son desagradables. Los SUV, por ejemplo, serían discutiblemente asquerosos incluso si funcionaran con un combustible que nunca se agotara y no generara 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 empieza a parecer una minucia. Si tienes el dinero, es más elegante pensar en todas las llamadas telefónicas como un mismo tipo de cosa, sin importar dónde esté la otra persona.

Hay un buen desperdicio, y un mal desperdicio. Estoy interesado en el buen desperdicio, el tipo en el que, gastando más, podemos obtener diseños más simples. ¿Cómo vamos a aprovechar las oportunidades de desperdiciar ciclos que vamos a obtener con el nuevo hardware más rápido?

El deseo de velocidad está tan profundamente arraigado en nosotros, con nuestras computadoras enclenques, que se necesitará un esfuerzo consciente para superarlo. En el diseño del lenguaje, deberíamos estar buscando conscientemente situaciones en las que podamos intercambiar eficiencia por incluso la más pequeña mejora en la comodidad.

La mayoría de las estructuras de datos existen por la velocidad. Por ejemplo, muchos lenguajes hoy en día tienen cadenas y 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 datos separado? Realmente no lo necesitas. Las cadenas solo existen por eficiencia. Pero es una pena que la semántica del lenguaje se atasque con hacks para que los programas funcionen 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, seguramente es una porquería tener axiomas adicionales que no añaden ningún 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 la implementación. En lugar de tener listas y cadenas, solo hay listas, con alguna manera de dar al compilador consejos de optimización que le permitan desplegar las cadenas como bytes contiguos si es necesario.

Dado que la velocidad no importa en la mayor parte de un programa, no tendrás que molestarte normalmente con este tipo de microgestión. Esto será cada vez más cierto a medida que las computadoras sean 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 está escribiendo un programa, y esto no es solo inevitable, sino deseable.

La palabra "ensayo" proviene del verbo francés "essayer", que significa "probar". Un ensayo, en el sentido original, es algo que escribes para tratar de entender algo. Esto ocurre en el software también. 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 tratando de escribir.

Los hackers de Lisp ya conocen 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 sorprendentemente ineficientes que se necesita un esfuerzo consciente para no pensar en lo que están haciendo, de la misma manera 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, más que nada, es un lenguaje en el que se pueda juntar una increíblemente ineficiente versión 1 de un programa con el menor esfuerzo posible. Al menos, así es como lo describiríamos en términos de hoy. Lo que dirán es que quieren un lenguaje que sea fácil de programar.

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

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

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

Hay perspectivas aún más impactantes que esas. 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 los números como listas en la práctica. De hecho, el artículo de McCarthy de 1960 no estaba, en ese momento, pensado para 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 sí, inesperadamente, tomó este artículo y lo tradujo en un intérprete de Lisp que funcionara, los números ciertamente no se representaron como listas; se representaron en binario, como en todos los demás lenguajes.

¿Podría un lenguaje de programación llegar a deshacerse de los números como tipo de datos fundamental? No lo pregunto tanto como una pregunta seria como como una forma de jugar al pollo con el futuro. Es como el caso hipotético de una fuerza irresistible que se encuentra con un objeto inmóvil, 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 núcleo del lenguaje, ese parecería ser el lado en el que apostar a medida que t se acerca al infinito. Si la idea sigue pareciendo insoportable dentro de cien años, quizás no lo sea dentro de mil.

Para que quede claro, no estoy proponiendo que todos los cálculos numéricos se lleven a cabo realmente utilizando listas. Estoy proponiendo que el lenguaje central, antes de cualquier notación adicional sobre la implementación, se defina de esta manera. En la práctica, cualquier programa que quiera hacer alguna cantidad de matemáticas probablemente representará los números en binario, pero esto sería una optimización, no parte de la semántica del lenguaje central.

Otra forma de quemar ciclos es tener muchas capas de software entre la aplicación y el hardware. Esto también es una tendencia que vemos sucediendo ya: muchos lenguajes recientes son compilados en bytecode. Bill Woods una vez me dijo que, como regla general, cada capa de interpretación cuesta un factor de 10 en velocidad. Este coste extra te compra flexibilidad.

La primera versión de Arc fue un caso extremo de este tipo de lentitud multinivel, con los correspondientes beneficios. Fue un clásico intérprete "metacircular" escrito encima de Common Lisp, con una clara semejanza familiar con la función eval definida en el artículo original de McCarthy sobre Lisp. Todo era 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, funciona también encima de 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 ascendente significa escribir un programa como una serie de capas, cada una de las cuales sirve como un lenguaje para la que está encima. Este enfoque tiende a producir programas más pequeños y flexibles. También es el mejor camino para ese santo grial, la reutilización. Un lenguaje es por definición reutilizable. Cuanto más de tu aplicación puedas empujar hacia abajo a un lenguaje para escribir ese tipo de aplicación, más reutilizable será tu software.

De alguna manera, la idea de la reutilización se ha unido a la programación orientada a objetos en los años 80, y ninguna cantidad de evidencia en contra parece poder deshacerla. Pero aunque algo de software orientado a objetos es reutilizable, lo que lo hace reutilizable es su carácter ascendente, no su orientación a objetos. Considera las bibliotecas: son reutilizables porque son lenguaje, tanto si se escriben en un estilo orientado a objetos como si no.

No predigo la desaparición de la programación orientada a objetos, por cierto. 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. 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, más nos vale hablar de la computación paralela, porque ahí es donde esta idea parece vivir. Es decir, sin importar cuándo estés hablando, la computación paralela parece ser algo que va a suceder en el futuro.

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

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

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

Y esto será, al igual que pedir implementaciones específicas de datos estructuras, algo que se hará bastante tarde en la vida de un programa, cuando se intente optimizarlo. Las versiones 1 normalmente ignoran cualquier ventaja que se pueda obtener de la computación paralela, del mismo modo que ignoran las ventajas que se pueden obtener de las representaciones específicas de los 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 que hay un montón 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 compensaciones entre velocidad y comodidad, 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 ampliamente utilizados dentro de cien años. Parte de la razón por la que digo esto es el 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 sin embargo con el consejo de optimización adecuado al compilador, también produciría código muy rápido cuando fuera necesario. Así que, como soy optimista, voy a 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 pueden abarcar la mayor parte de ella.

A medida que esta brecha se amplíe, los perfiladores serán cada vez más importantes. Ahora mismo se presta poca atención a la creación de perfiles. Mucha gente sigue creyendo 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, se hará 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 que solo haya unos pocos lenguajes, no estoy incluyendo "pequeños lenguajes" específicos del dominio. Creo que esos lenguajes integrados son una gran idea, y espero que proliferen. Pero espero que estén escritos como pieles lo suficientemente delgadas como para que los usuarios puedan ver el lenguaje de propósito general que hay debajo.

¿Quién diseñará los lenguajes del futuro? Una de las más emocionantes tendencias 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 tomado por los hackers. Los resultados hasta ahora son un poco desastrosos, pero alentadores. Hay algunas ideas sorprendentemente novedosas en Perl, por ejemplo. Muchas son sorprendentemente malas, pero eso siempre es cierto en 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ñen (algunos de los mejores hackers que conozco son profesores), pero sí es cierto que hay una gran cantidad de cosas que los que enseñan no pueden hacer. La investigación impone restricciones de castas restrictivas. En cualquier campo académico hay temas en los que está bien trabajar y otros que no lo están. Desafortunadamente, la distinción entre temas aceptables y prohibidos suele basarse en lo intelectual que suene el trabajo cuando se describe en artículos de investigación, más que en lo importante que sea para obtener buenos resultados. El caso extremo es probablemente la literatura; la gente que estudia literatura rara vez dice nada que sea de la menor utilidad para los que la producen.

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

La tendencia no es solo hacia el desarrollo de los lenguajes como proyectos de código abierto más que como "investigación", sino hacia los lenguajes diseñados por los programadores de aplicaciones que los necesitan para 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 en principio puede ser posible diseñar un lenguaje ahora que resultara atractivo para 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 tan bien hoy como dentro de cien años.

¿Qué programa a uno le gustaría escribir? Lo que menos trabajo requiera. Excepto que no del todo: lo que sería menos trabajo si tus ideas sobre la programación no estuvieran ya influenciadas por los lenguajes que estás usando actualmente. Esa influencia puede ser tan generalizada que se necesita un gran esfuerzo para superarla. Uno pensaría que sería evidente 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 ser tan limitadas por el lenguaje en el que pensamos que las formulaciones más fáciles de los programas parecen muy sorprendentes. Son algo que tienes que descubrir, no algo en lo que naturalmente te hundas.

Un truco útil aquí es utilizar la longitud del programa como una aproximación para 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 requiere para escribir, pero es lo suficientemente cerca como para que estés mejor apuntando a la sólida diana de la brevedad que a la difusa y cercana del menor trabajo. Entonces el algoritmo para el diseño del lenguaje 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ás en diferentes grados dependiendo de lo cerca que estés del núcleo. Las rutinas de clasificación puedes escribirlas ahora. Pero sería difícil predecir ahora qué tipo de bibliotecas se podrían necesitar en cien años. Presumiblemente, muchas bibliotecas serán para dominios que ni siquiera existen todavía. Si SETI@home funciona, por ejemplo, vamos a necesitar bibliotecas para comunicarnos con alienígenas. A menos que, por supuesto, sean lo suficientemente avanzados como para que ya se comuniquen en XML.

En el otro extremo, creo que podrías diseñar el lenguaje central hoy. De hecho, algunos podrían argumentar que ya fue diseñado en gran parte 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 de hoy en día hubieran estado disponibles en 1960, ¿alguien habría querido usarlos?

En cierto modo, la respuesta es no. Los lenguajes de hoy en día asumen infraestructuras que no existían en 1960. Por ejemplo, un lenguaje en el que la sangría es significativa, como Python, no funcionaría muy bien en las terminales de impresora. Pero dejando de lado esos problemas (suponiendo, por ejemplo, que todos los programas se escribieran simplemente en papel), ¿les habría gustado a los programadores de los años 60 escribir programas en los lenguajes que usamos ahora?

Creo que sí. Algunos de los menos imaginativos, que tenían artefactos de los primeros lenguajes integrados en sus ideas de 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 ningún problema en aprovechar al máximo los lenguajes actuales, si los hubieran tenido.

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

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

Cuando se trabaja en el diseño de un lenguaje, creo que es bueno tener un objetivo así y mantenerlo conscientemente en mente. Cuando se aprende a conducir, uno de los principios que se te enseñan es alinear el coche no alineando el capó con las rayas pintadas en la carretera, sino apuntando a un punto en la distancia. Incluso si lo único que te importa es lo que ocurre en los siguientes diez pies, esta es la respuesta correcta. Creo que podemos y deberíamos 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 simplemente consejos de optimización, y no cambiarían el significado de un programa correcto. Common Lisp parece haber sido el primero en establecerlo 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.