Loading...

EL LENGUAJE DE CIEN AÑOS

Original

abril 2003

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

Es difícil predecir cómo será la vida dentro de cien años. Solo hay algunas 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 todas 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 controla esos coches voladores?

Vale la pena pensar en esto no tanto porque realmente lleguemos a usar estos lenguajes, sino porque, si tenemos suerte, usaremos lenguajes en el camino desde este punto hasta aquel.

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

Predigo un destino similar para Java. A veces, la gente 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 estanterías ocupado por libros sobre él (particularmente libros individuales sobre él), o por el número de estudiantes de pregrado 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 conjetura. Puedo estar equivocado. Mi punto aquí no es despreciar a Java, sino plantear el tema de los árboles evolutivos y hacer que la gente se pregunte, ¿dónde en el árbol está el lenguaje X? 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 cualquier momento dado, probablemente esté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 cro-magnones habrían estado constantemente viniendo 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 de Fortran, por ejemplo, parece estar fusionándose con los descendientes de Algol. En teoría, esto también es posible para las especies, pero no es probable que haya sucedido con 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 más pequeño, 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 hacia dónde es probable que conduzca la evolución de los lenguajes de programación, porque pueden orientarse en consecuencia. En ese caso, "mantenerse en una rama principal" se convierte en 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 podría, en principio, 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 debes considerar la ubicación antes que nada. Todo lo demás se puede arreglar más tarde, pero no puedes cambiar 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 sentido esto acerca de los axiomas: cuantos menos, mejor, y creo que tienen razón.

Al menos, debe ser un ejercicio útil mirar de cerca el núcleo de un lenguaje para ver si hay axiomas que podrían eliminarse. He descubierto en mi larga carrera como un desaliñado que el exceso genera más exceso, y he visto esto suceder en el software, así 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 cómo serán los lenguajes de programación dentro de cien años. ¿Estaremos siquiera escribiendo programas dentro de cien años? ¿No simplemente le diremos a las computadoras lo que queremos que hagan?

No ha habido mucho progreso en ese departamento hasta ahora. Mi conjetura es que dentro de cien años la gente seguirá diciéndole a las computadoras qué hacer usando programas que reconoceríamos como tales. Puede haber tareas que resolvemos 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 recuerda que ya tenemos casi cincuenta años de historia detrás de nosotros. Mirar hacia adelante cien años es una idea comprensible cuando consideramos cuán lentamente han evolucionado los lenguajes en los últimos cincuenta.

Los lenguajes evolucionan lentamente porque no son realmente tecnologías. Los lenguajes son notación. Un programa es una descripción formal del 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 parecida a la tasa de evolución en la notación matemática que, digamos, en el transporte o las comunicaciones. La notación matemática sí evoluciona, pero no con los saltos gigantes que ves en la tecnología.

Cualquiera que sea el material del que estén hechas las computadoras dentro de cien años, parece seguro predecir que serán mucho más rápidas de lo que son ahora. Si la Ley de Moore sigue funcionando, serán 74 quintillones (73,786,976,294,838,206,464) de veces más rápidas. Eso es un poco 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 dejará de funcionar. Cualquier cosa que se supone que debe duplicarse cada dieciocho meses parece probable que eventualmente se enfrente a algún tipo de límite fundamental. Pero no tengo problemas para creer que las computadoras serán mucho más rápidas. Incluso si solo terminan siendo un miserable millón de veces más rápidas, eso debería cambiar las reglas del juego para los lenguajes de programación de manera sustancial. Entre otras cosas, habrá más espacio para lo que ahora se consideraría lenguajes lentos, es decir, lenguajes que no producen un código muy eficiente.

Y, sin embargo, algunas aplicaciones seguirán exigiendo velocidad. Algunos de los problemas que queremos resolver con computadoras son creados por computadoras; por ejemplo, la tasa a la que tienes que procesar imágenes de video depende de la tasa a la que otra computadora puede generarlas. Y hay otra clase de problemas que inherentemente tienen una capacidad ilimitada para absorber ciclos: renderización 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 ofrecer, las computadoras más rápidas significarán que los lenguajes tendrán que cubrir un rango cada vez más amplio de eficiencias. Ya hemos visto esto suceder. Las implementaciones actuales de algunos lenguajes nuevos 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. La gente de hace treinta años se habría sorprendido de lo casualmente que hacemos llamadas telefónicas de larga distancia. La gente de hace cien años se habría sorprendido aún más de que un paquete viajaría algún día de Boston a Nueva York a través de Memphis.

Ya puedo decirte lo que va a suceder con todos esos ciclos extra que el hardware más rápido nos dará en los próximos cien años. Casi todos se desperdiciarán.

Aprendí a programar cuando el poder de la computadora era escaso. Recuerdo haber eliminado todos los espacios de mis programas en Basic para que encajaran en la memoria de un TRS-80 de 4K. La idea de todo este software increíblemente ineficiente consumiendo ciclos haciendo lo mismo una y otra vez me parece un poco repugnante. Pero creo que mis intuiciones aquí están equivocadas. Soy como alguien que creció en la pobreza y no puede soportar gastar dinero incluso en algo importante, como ir al médico.

Algunos tipos de desperdicio son realmente repugnantes. Los SUV, por ejemplo, serían discutiblemente repugnantes incluso si funcionaran con un combustible que nunca se agotara y no generara contaminación. Los SUV son repugnantes porque son la solución a un problema repugnante. (Cómo hacer que las minivans se vean 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 comienza a parecer insignificante. 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, al gastar más, podemos obtener diseños más simples. ¿Cómo aprovecharemos las oportunidades de desperdiciar ciclos que obtendremos de nuevo hardware más rápido?

El deseo de velocidad está tan profundamente arraigado en nosotros, con nuestras computadoras insignificantes, que tomará un esfuerzo consciente superarlo. En el diseño de lenguajes, deberíamos buscar conscientemente situaciones donde podamos intercambiar eficiencia por incluso el más pequeño aumento en 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? No lo necesitas, realmente. Las cadenas solo existen por eficiencia. Pero es lamentable ensuciar la semántica del lenguaje con trucos para hacer 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, seguramente es repugnante 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 micromanagement. 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 está escribiendo 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 entender 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 exactamente qué estaban tratando de escribir cuando comenzaron.

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 tal manera que lo haga todo con listas. Estas versiones iniciales pueden ser tan increíblemente ineficientes que se requiere un esfuerzo consciente no pensar en lo que están haciendo, así como, al menos para mí, comer un filete requiere un esfuerzo consciente no pensar de dónde provino.

Lo que los programadores dentro de cien años buscarán, sobre todo, es un lenguaje donde puedas juntar una versión 1 increíblemente ineficiente de un programa con el menor esfuerzo posible. Al menos, así lo describiríamos en términos actuales. 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 se volverá cada vez más claro a medida que las computadoras se vuelvan más rápidas.

Creo que deshacerse de las cadenas es algo en lo que ya podríamos pensar. Lo hicimos en Arc, y parece ser una victoria; algunas operaciones que serían incómodas 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. ¿Desaparecerán los arreglos, por ejemplo? Después de todo, son solo un subconjunto de tablas hash donde las claves son vectores de enteros. ¿Reemplazaremos las tablas hash mismas con listas?

Hay perspectivas aún más sorprendentes que esa. 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. Simplemente es increíblemente 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 en un intérprete de Lisp funcional, los números ciertamente no se representaron como listas; se representaron en binario, como en cualquier otro lenguaje.

¿Podría un lenguaje de programación llegar tan lejos como para deshacerse de los números como un tipo de dato fundamental? Pregunto esto no tanto como una pregunta seria, sino como una forma de jugar a las adivinanzas con el futuro. Es como el caso hipotético de una fuerza irresistible encontrándose con un objeto inmóvil: aquí, una implementación increíblemente ineficiente encontrándose con recursos increíblemente grandes. No veo por qué no. El futuro es bastante largo. Si hay algo que podemos hacer para disminuir el número de axiomas en el lenguaje central, eso parecería ser el lado en el que apostar a medida que t se acerca a infinito. Si la idea aún parece insoportable dentro de cien años, tal vez no lo sea en mil.

Solo para ser claro al respecto, no estoy proponiendo que todos los cálculos numéricos se realicen 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 quisiera hacer cualquier 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 central.

Otra forma de consumir ciclos es tener muchas capas de software entre la aplicación y el hardware. Esto también es una tendencia que ya vemos suceder: muchos lenguajes recientes se compilan 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 costo adicional te compra flexibilidad.

La primera versión de Arc fue un caso extremo de este tipo de lentitud de múltiples niveles, con beneficios correspondientes. Era un clásico intérprete "metacircular" escrito sobre Common Lisp, con un evidente parecido familiar a la función eval definida en el artículo original de Lisp de McCarthy. Todo el conjunto 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 sobre un intérprete de bytecode. Así que aquí teníamos dos niveles de interpretación, uno de ellos (el superior) increíblemente ineficiente, y el lenguaje era utilizable. Apenas utilizable, 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 un lenguaje para la que está 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 abajo en 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 adjuntó a la programación orientada a objetos en la década de 1980, y ninguna cantidad de evidencia en contrario parece poder liberarla. Pero aunque algún software orientado a objetos es reutilizable, lo que lo hace reutilizable es su naturaleza de abajo hacia arriba, no su orientación a objetos. Considera las bibliotecas: son reutilizables porque son lenguaje, ya sea que estén escritas en un estilo orientado a objetos o 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. 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.

Mientras hablamos del futuro, es mejor que hablemos de la 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.

¿Alguna vez alcanzará el futuro a esto? 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 programación. ¿O no? Ya los diseñadores de chips tienen que pensar en ello, y también deben hacerlo las personas que intentan escribir software de sistemas en computadoras multiprocesador.

La verdadera pregunta es, ¿hasta qué punto llegará el paralelismo en la escalera 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 es invisible en el código fuente de las aplicaciones?

Una cosa que parece probable es que la mayoría de las oportunidades para el paralelismo se desperdiciarán. Este es un caso especial de mi predicción más general de que la mayor parte del poder extra de la computadora que se nos da se desperdiciará. Espero que, al igual que con la velocidad asombrosa 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 ordinarios sea más como poder bifurcar procesos que todos terminan ejecutándose en paralelo.

Y esto será, al igual que pedir implementaciones específicas de estructuras de datos, algo que harás bastante tarde en la vida de un programa, cuando intentes optimizarlo. Las versiones 1 normalmente ignorarán cualquier ventaja que se pueda obtener de la computación paralela, así como 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 optimización prematura si lo hiciera.

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

Y, sin embargo, puede que solo haya unos pocos lenguajes de uso general 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 hacer un lenguaje que fuera ideal para escribir una versión 1 lenta, y aún así, con el consejo de optimización correcto para el compilador, también generaría un código muy rápido cuando fuera necesario. Así que, dado que 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ía, los perfiles se volverán cada vez más importantes. Ahora 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ía, se volverá cada vez más claro que la forma de obtener aplicaciones rápidas es tener una buena guía de uno a otro.

Cuando digo que puede que solo haya unos pocos lenguajes, no estoy incluyendo "lenguajes pequeños" específicos de dominio. Creo que tales lenguajes embebidos son una gran idea, y espero que se multipliquen. Pero espero que se escriban como capas lo suficientemente delgadas 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 en los últimos diez años ha sido el auge de 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 sorprendentemente novedosas en Perl, por ejemplo. Muchas son sorprendentemente malas, pero eso siempre es cierto en los esfuerzos ambiciosos. A la tasa actual de mutación, Dios sabe en qué podría evolucionar Perl dentro de cien años.

No es cierto que quienes no pueden hacer, enseñen (algunos de los mejores hackers que conozco son profesores), pero es cierto que hay muchas cosas que aquellos que enseñan no pueden hacer. La investigación impone restricciones de casta limitantes. En cualquier campo académico hay temas que está bien trabajar y otros que no. Desafortunadamente, la distinción entre temas aceptables y prohibidos suele basarse 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 más mínima utilidad para quienes 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 inquietantemente pequeña. (Olin Shivers ha protestado elocuentemente sobre esto). Por ejemplo, los tipos parecen ser una fuente inagotable de artículos de investigación, a pesar de que la tipificación estática parece excluir verdaderas macros, sin las cuales, en mi opinión, ningún lenguaje vale la pena usar.

La tendencia no es meramente hacia lenguajes que se desarrollan como proyectos de código abierto en lugar de "investigación", sino hacia lenguajes diseñados por los programadores de aplicaciones que necesitan usarlos, en lugar de por 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 un lenguaje ahora 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 poder imaginar recursos ilimitados hoy tanto como dentro de cien años.

¿Qué programa te gustaría escribir? Lo que sea que requiera menos trabajo. Excepto que no del todo: lo que serí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 omnipresente que se requiere 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 en el que pensamos que formulaciones más fáciles de programas parecen muy sorprendentes. Son algo que tienes que descubrir, no algo en lo que te sumerjas naturalmente.

Un truco útil aquí es usar la longitud del programa como una aproximación de cuánto trabajo es 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 es el que menos trabajo requiere escribir, pero es lo suficientemente cercano como para que sea mejor apuntar al sólido objetivo de la brevedad que al difuso, cercano de menos 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 diferentes grados dependiendo de cuán cerca estés del núcleo. Las rutinas de ordenamiento que puedes escribir ahora. Pero sería difícil predecir ahora qué tipos de bibliotecas podrían ser necesarias dentro de cien años. Presumiblemente, muchas bibliotecas serán para dominios que ni siquiera existen aún. 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 ser capaz de diseñar el lenguaje central hoy. De hecho, algunos podrían argumentar que ya fue diseñado en su mayoría 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, ¿alguien habría querido usarlos?

En algunos aspectos, la respuesta es no. Los lenguajes de hoy 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 impresora. Pero dejando de lado tales problemas, asumiendo, por ejemplo, que los programas se escribieran todos en papel, ¿habrían disfrutado 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 de lo que era un programa, podrían haber tenido problemas. (¿Cómo puedes manipular datos sin hacer aritmética de punteros? ¿Cómo puedes implementar diagramas de flujo sin gotos?) Pero creo que los programadores más inteligentes no habrían tenido problemas para 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é 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. Podríamos tener que dar más consejos de optimización que los usuarios dentro de cien años, pero aún podría ser una victoria 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) tal lenguaje, si existiera, podría ser bueno para programar hoy. Cuando ves estas ideas expuestas 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 tal objetivo 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 todo lo 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 simplemente consejos de optimización, y no cambiarían el significado de un programa correcto. Common Lisp parece haber sido el primero en afirmar esto 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.