Loading...

EL LENGUAJE DE CIEN AÑOS

Original

Abril 2003

(Este ensayo se deriva de un discurso principal en PyCon 2003.)

Es difícil predecir cómo será la vida dentro de cien años. Hay solo unas pocas cosas que podemos decir con certeza. Sabemos que todos conducirán autos 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 serán entrenadas en las artes marciales. Aquí quiero enfocarme en un detalle de este panorama. ¿Qué tipo de lenguaje de programación usarán para escribir el software que controla esos autos voladores?

Vale la pena pensar en esto no tanto porque realmente vayamos a usar 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 ramificándose por todas partes. Ya podemos ver que esto está sucediendo. Cobol, a pesar de su popularidad en algún momento, no parece tener descendientes intelectuales. Es un callejón evolutivo, un lenguaje neandertal.

Predigo un destino similar para Java. A veces la gente me envía correos electrónicos 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 que ocupan los libros sobre él (particularmente 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 resultará ser un lenguaje exitoso, quiero decir algo más específico: que Java resultará ser un callejón evolutivo, como Cobol.

Esta es solo una conjetura. Puedo estar equivocado. Mi punto aquí no es criticar 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 seas más feliz en las ramas principales de un árbol evolutivo. Incluso cuando todavía había muchos neandertales, debe haber sido una mierda ser uno. Los cromagnones estarían 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 es posible para las especies también, pero es poco 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 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 se podría escribir en términos de estos operadores fundamentales.

Creo que los operadores fundamentales son el factor más importante para la supervivencia a largo plazo de un lenguaje. El resto lo puedes cambiar. Es como la regla de que al comprar una casa debes considerar la ubicación ante todo. 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 sentido que así debe ser con 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 un vago que la suciedad engendra suciedad, y he visto que esto sucede 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 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. ¿Estaremos escribiendo programas dentro de cien años? ¿No le diremos simplemente a las computadoras lo que queremos que hagan?

No ha habido mucho progreso en ese sentido hasta ahora. Mi conjetura es que dentro de cien años la gente seguirá diciéndoles 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 seguirá habiendo 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 abarcable cuando consideramos lo lentamente que han evolucionado los lenguajes en los últimos cincuenta.

Los lenguajes evolucionan lentamente porque realmente 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. Entonces, 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, en el transporte o las comunicaciones. La notación matemática evoluciona, pero no con los saltos gigantes que se ven en la tecnología.

Lo que sea que las computadoras estén hechas en cien años, parece seguro predecir que serán mucho más rápidas de lo que son 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 algo difícil de imaginar. E, 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 se duplique cada dieciocho meses parece probable que choque contra algún tipo de límite fundamental eventualmente. Pero no tengo problemas para creer que las computadoras serán mucho más rápidas. Incluso si terminan siendo solo un millón de veces más rápidas, eso debería cambiar las reglas básicas para los lenguajes de programación sustancialmente. Entre otras cosas, habrá más espacio para lo que ahora se consideraría lenguajes lentos, lo que significa lenguajes que no producen código muy eficiente.

Y sin embargo, algunas aplicaciones aún exigirán 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 otras continúan exigiendo toda la velocidad que el hardware puede entregar, las computadoras más rápidas significarán que los lenguajes tienen que cubrir un rango cada vez más amplio de eficiencias. Ya hemos visto que esto está sucediendo. Las implementaciones actuales de algunos lenguajes nuevos populares son sorprendentemente despilfarradoras 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 despilfarradoras. Las personas de hace treinta años se asombrarían de lo despreocupadamente que hacemos llamadas de larga distancia. Las personas de hace cien años se asombrarían aún más de que un paquete algún día viaje de Boston a Nueva York a través de Memphis.

Ya puedo decirte lo que le va a pasar a todos esos ciclos extra que el hardware más rápido nos va a dar en los próximos cien años. Casi todos van a ser desperdiciados.

Aprendí a programar cuando el poder de las computadoras era escaso. Puedo recordar sacar todos los espacios de mis programas de Basic para que se ajustaran a la memoria de un TRS-80 de 4K. La idea de todo este software increíblemente 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 puede soportar gastar dinero ni siquiera en algo importante, como ir al médico.

Algunos tipos de desperdicio realmente son asquerosos. Las SUV, por ejemplo, serían asquerosas incluso si funcionaran con un combustible que nunca se acabara y no generaran contaminación. Las SUV son asquerosas porque son la solución a un problema asqueroso. (Cómo hacer que las minivans se vean más masculinas). Pero no todo el desperdicio es malo. Ahora que tenemos la infraestructura para apoyarlo, 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 un buen desperdicio y un mal desperdicio. Me interesa el buen desperdicio, el tipo donde, gastando más, podemos obtener diseños más simples. ¿Cómo aprovecharemos las oportunidades de desperdiciar ciclos que obtendremos de un 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 estar buscando conscientemente situaciones donde podamos intercambiar eficiencia por 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 de texto como listas. Semánticamente, las cadenas de texto son más o menos un subconjunto de las listas en las que los elementos son caracteres. Entonces, ¿por qué necesitas un tipo de datos separado? Realmente no lo necesitas. Las cadenas de texto solo existen por eficiencia. Pero es lamentable abarrotar la semántica del lenguaje con trucos para hacer que los programas se ejecuten más rápido. Tener cadenas de texto 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 asqueroso tener axiomas adicionales que no agregan poder expresivo, simplemente por el bien de la eficiencia. La eficiencia es importante, pero no creo que esa sea la forma correcta de obtenerla.

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 de texto, tener solo listas, con alguna forma de dar al compilador consejos de optimización que le permitirán organizar las cadenas de texto como bytes contiguos si es necesario.

Dado que la velocidad no importa en la mayor parte de un programa, normalmente no necesitarás molestarte con 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. Los cambios de especificación mientras se escribe un programa no solo son inevitables, sino también deseables.

La palabra "ensayo" proviene del verbo francés "essayer", que significa "intentar". Un ensayo, en el sentido original, es algo que escribes para tratar de descubrir 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 para que lo haga todo con listas. Estas versiones iniciales pueden ser tan sorprendentemente ineficientes que se requiere un esfuerzo consciente para no pensar en lo que están haciendo, al igual que, al menos para mí, comer un bistec requiere un esfuerzo consciente para no pensar de dónde proviene.

Lo que los programadores dentro de cien años estarán buscando, sobre todo, es un lenguaje donde puedan armar 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 fácil de programar.

El software ineficiente no es asqueroso. Lo asqueroso es un lenguaje que hace que los programadores hagan un 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 de texto ya es algo en lo que podríamos pensar. Lo hicimos en Arc, y parece ser una mejora; algunas operaciones que serían incómodas 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 arreglos, 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 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 los 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 documento de McCarthy de 1960 no tenía, en ese momento, la intención de 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í tomó este documento y lo tradujo a un intérprete de Lisp en funcionamiento, 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 datos fundamental? Hago esta pregunta no tanto como una pregunta seria, sino como una forma de jugar a la gallina 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 central, esa parecería ser la apuesta a la que apostar a medida que t se acerca al infinito. Si la idea todavía parece insoportable en cien años, tal vez no lo será en mil.

Solo para dejar claro esto, 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 central del lenguaje.

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 ya estamos viendo que está ocurriendo: muchos lenguajes recientes se compilan en código de bytes. 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 le da flexibilidad.

La primera versión de Arc fue un caso extremo de este tipo de lentitud multinivel, con beneficios correspondientes. Era un intérprete "metacircular" clásico escrito sobre Common Lisp, con un parecido familiar a la función eval definida en el documento 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 código de bytes. 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á por encima. 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 puedas empujar tu aplicación 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 la reutilización se pegó a la programación orientada a objetos en la década de 1980, y no parece haber evidencia en contrario que pueda liberarla. Pero aunque parte del 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, ya sea que se hayan escrito en un estilo orientado a objetos o no.

Por cierto, no predigo el declive 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.

Mientras hablamos del futuro, es mejor que hablemos sobre el cálculo paralelo, porque ahí es donde parece vivir esta idea. Es decir, no importa cuándo estés hablando, el cálculo paralelo parece ser algo que va a suceder en el futuro.

¿Alguna vez el futuro lo alcanzará? La gente ha estado hablando sobre el cálculo paralelo como algo inminente durante al menos 20 años, y no ha afectado mucho la práctica de la programación hasta ahora. ¿O no lo ha hecho? Ya los diseñadores de chips tienen que pensar en ello, y también las personas que intentan escribir software de sistemas en computadoras multiprocesador.

La pregunta real es, ¿hasta dónde subirá el cálculo paralelo en la escalera de abstracción? ¿En cien años afectará incluso a los programadores de aplicaciones? ¿O será algo en lo que piensen los escritores de compiladores, pero que suele ser invisible en el código fuente de las aplicaciones?

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

Y esto, como 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 ignorarán normalmente cualquier ventaja que se pueda obtener del cálculo en paralelo, al igual que ignorarán las ventajas de las representaciones específicas de datos.

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

¿Cuántos lenguajes de programación habrá en cien años? Últimamente parece haber un gran número 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 intercambios entre velocidad y conveniencia, dependiendo de la aplicación. Si esta es una tendencia real, el hardware que tendremos en cien años solo debería aumentarla.

Y sin embargo, puede haber solo unos pocos lenguajes ampliamente utilizados en cien años. Parte de la razón por la que digo esto es el optimismo: parece que, si hiciera un trabajo realmente bueno, podría hacer un lenguaje que fuera ideal para escribir una versión 1 lenta, y sin embargo, con los consejos de optimización adecuados al compilador, también produciría código muy rápido cuando fuera necesario. Entonces, 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 puedan abarcar la mayor parte de ella.

A medida que esta brecha se amplíe, los perfiladores se volverán cada vez más importantes. Ahora se presta poca atención al perfilado. 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 uno a otro.

Cuando digo que puede haber solo unos pocos lenguajes, no estoy incluyendo los "pequeños lenguajes" específicos del dominio. Creo que esos lenguajes incrustados son una gran idea y espero que se multipliquen. Pero espero que se escriban con una capa lo suficientemente delgada como para que los usuarios puedan ver el lenguaje de propósito general subyacente.

¿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 los 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 de 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 quienes 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 limitantes. En cualquier campo académico, hay temas que se pueden trabajar y otros que no. Desafortunadamente, la distinción entre temas aceptables y prohibidos suele basarse en qué tan intelectual suena el trabajo cuando se describe en artículos de investigación, en lugar de qué tan importante es para obtener buenos resultados. El caso extremo probablemente sea la literatura; las personas que estudian literatura rara vez dicen algo que sería 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 le permite hacer y el tipo de trabajo que produce buenos lenguajes es sorprendentemente pequeña. (Olin Shivers ha gruñido elocuentemente sobre esto). Por ejemplo, los tipos parecen ser una fuente inagotable de artículos de investigación, a pesar del hecho de que el tipado estático parece excluir los verdaderos macros, sin los cuales, en mi opinión, ningún lenguaje vale la pena usar.

La tendencia no es simplemente 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 los escritores de compiladores. Esta parece una buena tendencia y espero que continúe.

A diferencia de la física dentro de cien años, que es casi imposible de predecir, creo que en principio puede ser posible 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 tan bien hoy como dentro de cien años.

¿Qué programa nos gustaría escribir? Lo que menos trabajo cueste. Excepto 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 generalizada que se necesita un gran esfuerzo para superarla. Uno pensaría 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 suelen estar 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 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 exactamente cierto que el programa más corto es 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 borroso, cercano de menos trabajo. Entonces, el algoritmo para el diseño de lenguajes se convierte en: mira un programa y pregúntate, ¿hay alguna forma de escribirlo que sea más corta?

En la práctica, escribir programas en un lenguaje imaginario de dentro de cien años funcionará en diferentes grados dependiendo de qué tan cerca estés del núcleo. Puedes escribir rutinas de ordenación ahora. Pero sería difícil predecir ahora qué tipos de bibliotecas podrían necesitarse dentro de cien años. Presumiblemente, muchas bibliotecas serán para dominios que ni siquiera existen todavía. 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 central hoy. De hecho, algunos podrían argumentar que ya se diseñó en su mayor 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 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, suponiendo, por ejemplo, que todos los programas se escribieran solo en papel, ¿a los programadores de la década de 1960 les habría gustado escribir programas en los lenguajes que usamos ahora?

Creo que sí. Algunos de los menos imaginativos, que tenían incorporados artefactos de lenguajes antiguos en sus ideas de lo que era un programa, podrían haber tenido problemas. (¿Cómo se pueden manipular los datos sin hacer aritmética de punteros? ¿Cómo se pueden implementar diagramas de flujo sin goto?) 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 sería un gran pseudocódigo. ¿Qué tal usarlo para escribir software? Dado que el lenguaje de cien años deberá generar código rápido para algunas aplicaciones, presumiblemente podría generar código lo suficientemente eficiente como para funcionar de manera aceptable en nuestro hardware. Tendríamos que dar más consejos de optimización que los usuarios dentro de cien años, pero aun 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 expuestas de esa manera, es difícil no pensar: ¿por qué no intentar escribir el lenguaje de cien años ahora?

Cuando trabajas en el diseño de un lenguaje, 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 automóvil no alineando el capó con las rayas pintadas en la carretera, sino apuntando a un 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 encarnar 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 declarar 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.