CINCO PREGUNTAS SOBRE EL DISEÑO DE LENGUAJES DE PROGRAMACIÓN
OriginalMayo 2001
(Estas son algunas notas que hice para un panel de discusión sobre el diseño de lenguajes de programación en el MIT el 10 de mayo de 2001.)
1. Los Lenguajes de Programación son para las Personas.
Los lenguajes de programación son la forma en que las personas se comunican con las computadoras. La computadora estaría igual de feliz hablando cualquier lenguaje que fuera inequívoco. La razón por la que tenemos lenguajes de alto nivel es porque las personas no pueden lidiar con el lenguaje de máquina. El propósito de los lenguajes de programación es evitar que nuestros pobres y frágiles cerebros humanos se vean abrumados por una masa de detalles.
Los arquitectos saben que algunos tipos de problemas de diseño son más personales que otros. Uno de los problemas de diseño más limpios y abstractos es el diseño de puentes. Allí, tu trabajo es principalmente una cuestión de cruzar una distancia dada con la menor cantidad de material. El otro extremo del espectro es el diseño de sillas. Los diseñadores de sillas tienen que pasar su tiempo pensando en los traseros humanos.
El software varía de la misma manera. Diseñar algoritmos para enrutar datos a través de una red es un problema agradable y abstracto, como diseñar puentes. Mientras que diseñar lenguajes de programación es como diseñar sillas: se trata de lidiar con las debilidades humanas.
La mayoría de nosotros odiamos admitir esto. Diseñar sistemas de gran elegancia matemática suena mucho más atractivo para la mayoría de nosotros que complacer a las debilidades humanas. Y hay un papel para la elegancia matemática: algunos tipos de elegancia hacen que los programas sean más fáciles de entender. Pero la elegancia no es un fin en sí mismo.
Y cuando digo que los lenguajes tienen que diseñarse para adaptarse a las debilidades humanas, no quiero decir que los lenguajes tengan que diseñarse para los malos programadores. De hecho, creo que deberías diseñar para los mejores programadores, pero incluso los mejores programadores tienen limitaciones. No creo que a nadie le guste programar en un lenguaje donde todas las variables fueran la letra x con subíndices enteros.
2. Diseña para Ti y Tus Amigos.
Si miras la historia de los lenguajes de programación, muchos de los mejores fueron lenguajes diseñados para que sus propios autores los usaran, y muchos de los peores fueron diseñados para que los usaran otras personas.
Cuando los lenguajes se diseñan para otras personas, siempre es un grupo específico de otras personas: personas no tan inteligentes como el diseñador del lenguaje. Así que obtienes un lenguaje que te habla como a un tonto. Cobol es el caso más extremo, pero muchos lenguajes están impregnados de este espíritu.
No tiene nada que ver con qué tan abstracto sea el lenguaje. C es bastante de bajo nivel, pero fue diseñado para que sus autores lo usaran, y por eso a los hackers les gusta.
El argumento a favor de diseñar lenguajes para los malos programadores es que hay más malos programadores que buenos programadores. Eso puede ser cierto. Pero esos pocos buenos programadores escriben un porcentaje desproporcionadamente grande del software.
Me interesa la pregunta, ¿cómo diseñas un lenguaje que les guste a los mejores hackers? Creo que esto es idéntico a la pregunta, ¿cómo diseñas un buen lenguaje de programación?, pero incluso si no lo es, es al menos una pregunta interesante.
3. Dale al Programador el Máximo Control Posible.
Muchos lenguajes (especialmente los diseñados para otras personas) tienen la actitud de una institutriz: intentan evitar que hagas cosas que creen que no son buenas para ti. Me gusta el enfoque opuesto: dale al programador el máximo control posible.
Cuando aprendí Lisp por primera vez, lo que más me gustó fue que me consideraba un socio igual. En los otros lenguajes que había aprendido hasta entonces, había el lenguaje y mi programa, escrito en el lenguaje, y los dos estaban muy separados. Pero en Lisp, las funciones y macros que escribía eran iguales a las que componían el lenguaje mismo. Podía reescribir el lenguaje si quería. Tenía el mismo atractivo que el software de código abierto.
4. Apunta a la Brevedad.
La brevedad se subestima e incluso se desprecia. Pero si miras en los corazones de los hackers, verás que realmente les encanta. ¿Cuántas veces has escuchado a los hackers hablar con cariño de cómo, digamos, en APL, podían hacer cosas increíbles con solo un par de líneas de código? Creo que cualquier cosa que a la gente realmente inteligente le encante de verdad vale la pena prestarle atención.
Creo que casi cualquier cosa que puedas hacer para acortar los programas es buena. Debería haber muchas funciones de biblioteca; todo lo que pueda ser implícito debería serlo; la sintaxis debería ser lacónica hasta la falta; incluso los nombres de las cosas deberían ser cortos.
Y no solo los programas deberían ser cortos. El manual también debería ser delgado. Una gran parte de los manuales se ocupa de aclaraciones y reservas y advertencias y casos especiales. Si te obligas a acortar el manual, en el mejor de los casos lo haces arreglando las cosas en el lenguaje que requerían tanta explicación.
5. Admite lo que es el Hackeo.
Mucha gente desea que el hackeo fuera matemáticas, o al menos algo parecido a una ciencia natural. Creo que el hackeo se parece más a la arquitectura. La arquitectura está relacionada con la física, en el sentido de que los arquitectos tienen que diseñar edificios que no se caigan, pero el objetivo real de los arquitectos es hacer grandes edificios, no hacer descubrimientos sobre la estática.
Lo que a los hackers les gusta hacer es hacer grandes programas. Y creo que, al menos en nuestra propia mente, tenemos que recordar que es una cosa admirable escribir grandes programas, incluso cuando este trabajo no se traduce fácilmente en la moneda intelectual convencional de los artículos de investigación. Intelectualmente, es tan valioso diseñar un lenguaje que a los programadores les encantará como diseñar uno horrible que encarne alguna idea sobre la que puedas publicar un artículo.
1. ¿Cómo Organizar Grandes Bibliotecas?
Las bibliotecas se están convirtiendo en un componente cada vez más importante de los lenguajes de programación. También se están volviendo más grandes, y esto puede ser peligroso. Si toma más tiempo encontrar la función de biblioteca que hará lo que quieres que escribirla tú mismo, entonces todo ese código no está haciendo nada más que engrosar tu manual. (Los manuales de Symbolics fueron un caso paradigmático). Así que creo que tendremos que trabajar en formas de organizar las bibliotecas. Lo ideal sería diseñarlas de tal manera que el programador pudiera adivinar qué llamada a la biblioteca haría lo correcto.
2. ¿Realmente a la Gente le Asusta la Sintaxis de Prefijo?
Este es un problema abierto en el sentido de que me he preguntado al respecto durante años y aún no sé la respuesta. La sintaxis de prefijo me parece perfectamente natural, excepto posiblemente para las matemáticas. Pero podría ser que gran parte de la impopularidad de Lisp se deba simplemente a tener una sintaxis poco familiar. Si se debe hacer algo al respecto, si es cierto, es otra cuestión.
3. ¿Qué se necesita para el software basado en el servidor?
Creo que muchas de las aplicaciones nuevas más emocionantes que se escriban en los próximos veinte años serán aplicaciones web, es decir, programas que se ejecuten en el servidor y se comuniquen con usted a través de un navegador web. Y para escribir este tipo de programas, es posible que necesitemos algunas cosas nuevas.
Una cosa que necesitaremos es soporte para la nueva forma en que se lanzan las aplicaciones basadas en el servidor. En lugar de tener uno o dos lanzamientos importantes al año, como en el software de escritorio, las aplicaciones basadas en el servidor se lanzan como una serie de pequeños cambios. Puede haber hasta cinco o diez lanzamientos al día. Y como regla general, todos usarán siempre la última versión.
¿Sabes cómo se pueden diseñar programas para que sean depurables? Pues bien, el software basado en el servidor también tiene que diseñarse para que sea modificable. Tienes que poder cambiarlo fácilmente, o al menos saber qué es un cambio pequeño y qué es uno importante.
Otra cosa que podría resultar útil para el software basado en el servidor, sorprendentemente, son las continuaciones. En el software basado en la web, se puede usar algo como el estilo de paso de continuación para obtener el efecto de subrutinas en el mundo inherentemente sin estado de una sesión web. Tal vez valdría la pena tener continuaciones reales, si no fuera demasiado costoso.
4. ¿Qué nuevas abstracciones quedan por descubrir?
No estoy seguro de lo razonable que es esta esperanza, pero una cosa que realmente me encantaría hacer, personalmente, es descubrir una nueva abstracción, algo que marcaría una diferencia tan grande como tener funciones de primera clase o recursión, o incluso parámetros clave. Esto puede ser un sueño imposible. Estas cosas no se descubren tan a menudo. Pero siempre estoy buscando.
1. Puedes usar el idioma que quieras.
Escribir programas de aplicación solía significar escribir software de escritorio. Y en el software de escritorio hay un gran sesgo hacia escribir la aplicación en el mismo idioma que el sistema operativo. Y así, hace diez años, escribir software prácticamente significaba escribir software en C. Con el tiempo, se desarrolló una tradición: los programas de aplicación no deben escribirse en idiomas inusuales. Y esta tradición tuvo tanto tiempo para desarrollarse que incluso las personas no técnicas, como los gerentes y los capitalistas de riesgo, también la aprendieron.
El software basado en el servidor acaba con todo este modelo. Con el software basado en el servidor, puedes usar cualquier idioma que quieras. Casi nadie lo entiende todavía (especialmente los gerentes y los capitalistas de riesgo). Unos pocos hackers lo entienden, y por eso incluso oímos hablar de nuevos lenguajes independientes como Perl y Python. No estamos escuchando sobre Perl y Python porque la gente los esté usando para escribir aplicaciones de Windows.
Lo que esto significa para nosotros, como personas interesadas en el diseño de lenguajes de programación, es que ahora potencialmente hay una audiencia real para nuestro trabajo.
2. La velocidad proviene de los perfiladores.
A los diseñadores de lenguajes, o al menos a los implementadores de lenguajes, les gusta escribir compiladores que generen código rápido. Pero no creo que esto sea lo que hace que los lenguajes sean rápidos para los usuarios. Knuth señaló hace mucho tiempo que la velocidad solo importa en algunos cuellos de botella críticos. Y cualquiera que lo haya intentado sabe que no se pueden adivinar dónde están estos cuellos de botella. Los perfiladores son la respuesta.
Los diseñadores de lenguajes están resolviendo el problema equivocado. Los usuarios no necesitan puntos de referencia para ejecutarse rápido. Lo que necesitan es un lenguaje que les pueda mostrar qué partes de sus propios programas necesitan ser reescritas. Ahí es donde se origina la velocidad en la práctica. Así que tal vez sería un beneficio neto si los implementadores de lenguajes dedicaran la mitad del tiempo que habrían dedicado a las optimizaciones del compilador a escribir un buen perfilador en su lugar.
3. Necesitas una aplicación para impulsar el diseño de un lenguaje.
Esto puede no ser una regla absoluta, pero parece que los mejores lenguajes evolucionaron junto con alguna aplicación que se estaba usando para escribir. C fue escrito por personas que lo necesitaban para la programación de sistemas. Lisp se desarrolló en parte para hacer diferenciación simbólica, y McCarthy estaba tan ansioso por empezar que estaba escribiendo programas de diferenciación incluso en el primer artículo sobre Lisp, en 1960.
Es especialmente bueno si tu aplicación resuelve algún problema nuevo. Eso tenderá a hacer que tu lenguaje tenga nuevas características que los programadores necesitan. Personalmente, estoy interesado en escribir un lenguaje que será bueno para escribir aplicaciones basadas en el servidor.
[Durante el panel, Guy Steele también hizo este punto, con la sugerencia adicional de que la aplicación no debe consistir en escribir el compilador para tu lenguaje, a menos que tu lenguaje esté destinado a escribir compiladores.]
4. Un lenguaje tiene que ser bueno para escribir programas desechables.
Sabes lo que es un programa desechable: algo que escribes rápidamente para alguna tarea limitada. Creo que si mirases a tu alrededor, descubrirías que muchos programas grandes y serios comenzaron como programas desechables. No me sorprendería que la mayoría de los programas comenzaran como programas desechables. Y entonces, si quieres hacer un lenguaje que sea bueno para escribir software en general, tiene que ser bueno para escribir programas desechables, porque ese es el estadio larvario de la mayoría del software.
5. La sintaxis está conectada a la semántica.
Es tradicional pensar que la sintaxis y la semántica son completamente separadas. Esto sonará impactante, pero puede que no lo sean. Creo que lo que quieres en tu lenguaje puede estar relacionado con cómo lo expresas.
Hablé recientemente con Robert Morris, y señaló que la sobrecarga de operadores es un beneficio mayor en los lenguajes con sintaxis infija. En un lenguaje con sintaxis de prefijo, cualquier función que definas es efectivamente un operador. Si quieres definir un más para un nuevo tipo de número que has creado, simplemente puedes definir una nueva función para sumarlos. Si haces eso en un lenguaje con sintaxis infija, hay una gran diferencia en apariencia entre el uso de un operador sobrecargado y una llamada a función.
1. Nuevos lenguajes de programación.
A finales de los años 70 estaba de moda diseñar nuevos lenguajes de programación. Recientemente no lo ha estado. Pero creo que el software basado en el servidor volverá a poner de moda los nuevos lenguajes. Con el software basado en el servidor, puedes usar cualquier lenguaje que quieras, así que si alguien diseña un lenguaje que realmente parece mejor que otros disponibles, habrá personas que se arriesguen y lo usen.
2. Tiempo compartido.
Richard Kelsey dio esto como una idea cuyo momento ha llegado de nuevo en el último panel, y estoy completamente de acuerdo con él. Mi conjetura (y la conjetura de Microsoft, al parecer) es que gran parte de la computación se trasladará del escritorio a servidores remotos. En otras palabras, el tiempo compartido ha vuelto. Y creo que se necesitará apoyo para ello a nivel de lenguaje. Por ejemplo, sé que Richard y Jonathan Rees han realizado mucho trabajo implementando la programación de procesos dentro de Scheme 48.
3. Eficiencia.
Recientemente parecía que las computadoras finalmente eran lo suficientemente rápidas. Cada vez más escuchábamos sobre el código de bytes, lo que me implica al menos que sentimos que tenemos ciclos de sobra. Pero no creo que los tengamos, con software basado en servidores. Alguien tendrá que pagar por los servidores en los que se ejecuta el software, y la cantidad de usuarios que pueden admitir por máquina será el divisor de su costo de capital.
Por lo tanto, creo que la eficiencia importará, al menos en los cuellos de botella computacionales. Será especialmente importante realizar E/S rápidamente, porque las aplicaciones basadas en servidores realizan mucha E/S.
Puede resultar que el código de bytes no sea una victoria, al final. Sun y Microsoft parecen estar enfrentándose en una especie de batalla de los códigos de bytes en este momento. Pero lo están haciendo porque el código de bytes es un lugar conveniente para insertarse en el proceso, no porque el código de bytes sea una buena idea en sí mismo. Puede resultar que todo este campo de batalla se pase por alto. Eso sería bastante divertido.
1. Clientes.
Esta es solo una conjetura, pero mi conjetura es que el modelo ganador para la mayoría de las aplicaciones será puramente basado en el servidor. Diseñar software que funcione con el supuesto de que todos tendrán su cliente es como diseñar una sociedad con el supuesto de que todos simplemente serán honestos. Ciertamente sería conveniente, pero tienes que asumir que nunca sucederá.
Creo que habrá una proliferación de dispositivos que tengan algún tipo de acceso web, y todo lo que podrás asumir sobre ellos es que pueden admitir HTML y formularios sencillos. ¿Tendrás un navegador en tu teléfono celular? ¿Habrá un teléfono en tu asistente personal? ¿Tu blackberry obtendrá una pantalla más grande? ¿Podrás navegar por la web en tu gameboy? ¿En tu reloj? No lo sé. Y no tengo que saberlo si apuesto a que todo simplemente estará en el servidor. Es mucho más sólido tener todos los cerebros en el servidor.
2. Programación Orientada a Objetos.
Me doy cuenta de que este es un tema controvertido, pero no creo que la programación orientada a objetos sea gran cosa. Creo que es un modelo adecuado para ciertos tipos de aplicaciones que necesitan ese tipo específico de estructura de datos, como sistemas de ventanas, simulaciones y programas CAD. Pero no veo por qué debería ser el modelo para toda la programación.
Creo que parte de la razón por la que a la gente en las grandes empresas les gusta la programación orientada a objetos es porque genera mucho de lo que parece trabajo. Algo que naturalmente se representaría como, digamos, una lista de enteros, ahora se puede representar como una clase con todo tipo de andamiaje y ajetreo.
Otro atractivo de la programación orientada a objetos es que los métodos le dan algo del efecto de las funciones de primera clase. Pero esto es una noticia vieja para los programadores de Lisp. Cuando tienes funciones de primera clase reales, puedes usarlas de la manera que sea apropiada para la tarea en cuestión, en lugar de forzar todo en un molde de clases y métodos.
Lo que esto significa para el diseño de lenguajes, creo, es que no deberías construir la programación orientada a objetos demasiado profundamente. Tal vez la respuesta sea ofrecer cosas más generales y subyacentes, y dejar que la gente diseñe los sistemas de objetos que quiera como bibliotecas.
3. Diseño por Comité.
Tener tu lenguaje diseñado por un comité es una gran trampa, y no solo por las razones que todos conocen. Todos saben que los comités tienden a producir diseños irregulares e inconsistentes. Pero creo que un peligro mayor es que no tomarán riesgos. Cuando una sola persona está a cargo, puede tomar riesgos que un comité nunca aprobaría.
¿Es necesario tomar riesgos para diseñar un buen lenguaje, sin embargo? Muchas personas podrían sospechar que el diseño de lenguajes es algo en lo que debes mantenerte bastante cerca de la sabiduría convencional. Apuesto a que esto no es cierto. En todo lo demás que la gente hace, la recompensa es proporcional al riesgo. ¿Por qué el diseño de lenguajes debería ser diferente?