CINCO PREGUNTAS SOBRE EL DISEÑO DEL LENGUAJE
OriginalMayo de 2001
(Éstas son algunas notas que hice para un panel de discusión sobre diseño de lenguajes de programación en el MIT el 10 de mayo de 2001.)
1. Los lenguajes de programación son para 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 no fuera ambiguo. La razón por la que tenemos lenguajes de alto nivel es porque las personas no pueden manejar el lenguaje de las máquinas. El objetivo 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 claros y abstractos es el diseño de puentes. En este caso, el trabajo consiste en gran medida en salvar una distancia determinada con la menor cantidad de material posible. El otro extremo del espectro es el diseño de sillas. Los diseñadores de sillas tienen que dedicar su tiempo a pensar en 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.
A la mayoría de nosotros nos disgusta reconocerlo. Diseñar sistemas de gran elegancia matemática nos parece mucho más atractivo que complacer las debilidades humanas. Y la elegancia matemática tiene un papel que desempeñar: algunos tipos de elegancia hacen que los programas sean más fáciles de entender, pero la elegancia no es un fin en sí misma.
Y cuando digo que los lenguajes tienen que ser diseñados para adaptarse a las debilidades humanas, no quiero decir que los lenguajes tengan que ser diseñados para malos programadores. De hecho, creo que se deben 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 sean la letra x con subíndices enteros.
2. Diseña para ti y tus amigos.
Si analizamos la historia de los lenguajes de programación, muchos de los mejores fueron lenguajes diseñados para que los usaran sus propios autores, y muchos de los peores fueron diseñados para que los usaran otras personas.
Cuando los lenguajes están diseñados para otras personas, siempre se trata de un grupo específico de personas: personas no tan inteligentes como el diseñador del lenguaje. De modo que el resultado es un lenguaje que te habla con condescendencia. Cobol es el caso más extremo, pero muchos lenguajes están impregnados de este espíritu.
No tiene nada que ver con lo abstracto que sea el lenguaje. C es un lenguaje de muy bajo nivel, pero fue diseñado para que lo usen sus autores, y es por eso que a los hackers les gusta.
El argumento a favor de diseñar lenguajes para malos programadores es que hay más programadores malos que buenos. Puede que sea así, pero esos pocos buenos programadores escriben un porcentaje desproporcionadamente grande del software.
Me interesa la pregunta: ¿cómo se diseña un lenguaje que guste a los mejores hackers? Creo que es idéntica a la pregunta: ¿cómo se diseña un buen lenguaje de programación?, pero incluso si no lo es, al menos es una pregunta interesante.
3. Darle al programador el mayor control posible.
Muchos lenguajes (sobre todo los diseñados para otras personas) tienen la actitud de una institutriz: intentan impedir que hagas cosas que creen que no son buenas para ti. A mí me gusta el enfoque opuesto: darle al programador todo el control que puedas.
Cuando aprendí a usar Lisp, lo que más me gustó fue que me consideraba un socio igualitario. En los otros lenguajes que había aprendido hasta entonces, estaba el lenguaje y estaba mi programa, escrito en el lenguaje, y los dos estaban muy separados. Pero en Lisp, las funciones y macros que escribía eran exactamente las mismas que componían el lenguaje en sí. Podía reescribir el lenguaje si quería. Tenía el mismo atractivo que el software de código abierto.
4. Procura ser breve.
La brevedad es algo que se subestima e incluso se desprecia, pero si observamos el corazón de los hackers, veremos que realmente les encanta. ¿Cuántas veces hemos oído a los hackers hablar con cariño de cómo, por ejemplo, en APL podían hacer cosas increíbles con tan solo un par de líneas de código? Creo que vale la pena prestar atención a todo aquello que a la gente realmente inteligente le encanta.
Creo que casi todo lo que se pueda hacer para acortar los programas es bueno. Debería haber muchas funciones de biblioteca; todo lo que pueda ser implícito debería serlo; la sintaxis debería ser concisa hasta el extremo; incluso los nombres de las cosas deberían ser breves.
Y no sólo los programas deben ser breves. El manual también debe ser breve. Una buena parte de los manuales está llena de aclaraciones, reservas, advertencias y casos especiales. Si te obligas a acortar el manual, en el mejor de los casos lo haces corrigiendo las cosas en el lenguaje que requirieron tanta explicación.
5. Admita lo que es el hacking.
Mucha gente desearía que el hacking fuera una cuestión de matemáticas, o al menos algo parecido a una ciencia natural. Yo creo que el hacking 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 derrumben, pero el objetivo real de los arquitectos es hacer grandes edificios, no hacer descubrimientos sobre estática.
Lo que a los hackers les gusta hacer es crear programas geniales. Y creo que, al menos en nuestra mente, tenemos que recordar que escribir programas geniales es algo admirable, incluso cuando este trabajo no se traduce fácilmente en la moneda intelectual convencional de los artículos de investigación. Intelectualmente, vale la pena diseñar un lenguaje que les encante a los programadores tanto como diseñar uno horrible que incorpore alguna idea sobre la que se pueda 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 están creciendo, y esto puede ser peligroso. Si lleva más tiempo encontrar la función de biblioteca que hará lo que quieres que escribirla tú mismo, entonces todo ese código no hará más que engordar tu manual. (Los manuales de Symbolics fueron un buen ejemplo). Por eso creo que tendremos que trabajar en formas de organizar las bibliotecas. Lo ideal sería diseñarlas de modo que el programador pudiera adivinar qué llamada de biblioteca haría lo correcto.
2. ¿La gente realmente tiene miedo de la sintaxis de los prefijos?
Este es un problema abierto en el sentido de que me lo he planteado durante años y todavía no sé la respuesta. La sintaxis de prefijos 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 que tiene una sintaxis desconocida. Si se debe hacer algo al respecto, si es cierto, es otra cuestión.
3. ¿Qué necesitas para el software basado en servidor?
Creo que muchas de las aplicaciones más interesantes que se escribirán en los próximos veinte años serán aplicaciones basadas en la Web, es decir, programas que se alojan en el servidor y se comunican con el usuario 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 servidor. En lugar de tener uno o dos grandes lanzamientos al año, como el software de escritorio, las aplicaciones basadas en servidor se lanzan como una serie de pequeños cambios. Es posible que haya hasta cinco o diez lanzamientos al día y, por regla general, todos usarán siempre la última versión.
¿Sabes cómo diseñar programas que se puedan depurar? Bueno, el software basado en servidor también debe diseñarse para que se pueda modificar. Debes poder cambiarlo fácilmente o, al menos, saber qué es un cambio pequeño y qué es un cambio trascendental.
Otra cosa que podría resultar útil para el software basado en servidor, sorprendentemente, son las continuaciones. En el software basado en la Web, se puede utilizar algo como el estilo de paso de continuación para obtener el efecto de las 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 cuán razonable sea 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 de palabras clave. Puede que sea un sueño imposible. Estas cosas no se descubren tan a menudo, pero siempre estoy buscando.
1. Puedes usar el idioma que quieras.
Antes, escribir programas de aplicación significaba escribir software de escritorio, y en este ámbito existe una gran tendencia a escribir la aplicación en el mismo lenguaje que el sistema operativo. Por eso, hace diez años, escribir software significaba escribir software en C. Con el tiempo, se desarrolló una tradición: los programas de aplicación no deben escribirse en lenguajes inusuales. Y esta tradición tardó tanto en desarrollarse que también la aprendieron personas sin conocimientos técnicos, como gerentes y capitalistas de riesgo.
El software basado en servidor hace añicos todo este modelo. Con él se puede utilizar cualquier lenguaje que se desee. Casi nadie lo entiende todavía (especialmente los directivos y los inversores de capital riesgo). Unos pocos hackers lo entienden, y por eso oímos hablar de nuevos lenguajes independientes como Perl y Python. No oímos hablar de Perl y Python porque la gente los esté utilizando para escribir aplicaciones de Windows.
Lo que esto significa para nosotros, como personas interesadas en diseñar lenguajes de programación, es que ahora hay potencialmente una audiencia real para nuestro trabajo.
2. La velocidad viene 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 unos pocos cuellos de botella críticos. Y cualquiera que lo haya probado sabe que no se puede 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 pruebas comparativas para ejecutar programas rápidamente. Lo que necesitan es un lenguaje que les muestre qué partes de sus propios programas necesitan ser reescritas. De ahí proviene la velocidad en la práctica. Por lo tanto, tal vez sería una ganancia neta si los implementadores de lenguajes tomaran la mitad del tiempo que habrían dedicado a realizar optimizaciones del compilador y lo dedicaran a escribir un buen generador de perfiles.
3. Necesita una aplicación para impulsar el diseño de un lenguaje.
Puede que no sea una regla absoluta, pero parece que los mejores lenguajes evolucionaron junto con alguna aplicación para la que se utilizaban. 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 ya escribía programas de diferenciación en el primer artículo sobre Lisp, en 1960.
Es especialmente bueno si su aplicación resuelve algún problema nuevo. Eso tenderá a impulsar su lenguaje a tener nuevas características que los programadores necesitan. Personalmente, me interesa escribir un lenguaje que sea bueno para escribir aplicaciones basadas en servidor.
[Durante el panel, Guy Steele también planteó este punto, con la sugerencia adicional de que la aplicación no debería consistir en escribir el compilador para su lenguaje, a menos que su lenguaje esté destinado a escribir compiladores.]
4. Un lenguaje tiene que ser bueno para escribir programas desechables.
Ya sabes lo que es un programa desechable: algo que escribes rápidamente para una tarea limitada. Creo que si mirases a tu alrededor, verías que muchos programas grandes y serios empezaron como programas desechables. No me sorprendería que la mayoría de los programas empezaran como programas desechables. Por eso, si quieres crear un lenguaje que sea bueno para escribir software en general, tiene que ser bueno para escribir programas desechables, porque esa es la etapa larvaria de la mayoría del software.
5. La sintaxis está conectada con la semántica.
Tradicionalmente, se piensa que la sintaxis y la semántica son cosas completamente independientes. Puede sonar chocante, pero puede que no sea así. Creo que lo que quieres en tu idioma puede estar relacionado con la forma en que lo expresas.
Hace poco estuve hablando con Robert Morris y me señaló que la sobrecarga de operadores es una gran ventaja 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 signo más para un nuevo tipo de número que hayas inventado, puedes simplemente definir una nueva función para agregarlos. 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 una función.
1. Nuevos lenguajes de programación.
En 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 servidor volverá a poner de moda los nuevos lenguajes. Con el software basado en servidor, puedes usar cualquier lenguaje que quieras, así que si alguien diseña un lenguaje que en realidad parece mejor que otros que están disponibles, habrá gente que se arriesgue y lo use.
2. Tiempo compartido.
Richard Kelsey presentó esta idea en el último panel y estoy completamente de acuerdo con él. Mi suposición (y la suposición de Microsoft, al parecer) es que gran parte de la informática se trasladará del escritorio a servidores remotos. En otras palabras, el tiempo compartido ha vuelto. Y creo que será necesario que haya soporte para ello a nivel de lenguaje. Por ejemplo, sé que Richard y Jonathan Rees han trabajado mucho en la implementación de la programación de procesos dentro de Scheme 48.
3. Eficiencia.
Recientemente, parecía que los ordenadores eran finalmente lo suficientemente rápidos. Cada vez oíamos hablar más del código de bytes, lo que, al menos para mí, implica que creemos que tenemos ciclos de sobra. Pero no creo que sea así con el software basado en servidores. Alguien tendrá que pagar por los servidores en los que se ejecuta el software, y la cantidad de usuarios que puedan soportar por máquina será el divisor de su coste de capital.
Por lo tanto, creo que la eficiencia será importante, al menos en los cuellos de botella computacionales. Será especialmente importante realizar operaciones de entrada y salida rápidamente, porque las aplicaciones basadas en servidor realizan muchas operaciones de entrada y salida.
Puede que al final el código byte no sea la solución. Sun y Microsoft parecen estar enfrentándose en una especie de batalla de códigos byte en este momento. Pero lo hacen porque el código byte es un lugar conveniente para insertarse en el proceso, no porque el código byte sea en sí una buena idea. Puede que se evite todo este campo de batalla. Eso sería bastante divertido.
1. Clientes.
Esto es sólo una suposición, pero creo que el modelo ganador para la mayoría de las aplicaciones será el basado puramente en servidores. Diseñar un software que funcione suponiendo que todo el mundo tendrá su cliente es como diseñar una sociedad suponiendo que todo el mundo será honesto. Sin duda sería conveniente, pero hay que asumir que nunca sucederá.
Creo que habrá una proliferación de dispositivos que tengan algún tipo de acceso a la Web, y todo lo que se podrá suponer sobre ellos es que pueden soportar HTML y formularios simples. ¿Tendrás un navegador en tu teléfono móvil? ¿Habrá un teléfono en tu Palm Pilot? ¿Tu Blackberry tendrá una pantalla más grande? ¿Podrás navegar por la Web en tu Gameboy? ¿En tu reloj? No lo sé. Y no tengo por qué saberlo si apuesto a que todo estará en el servidor. Es mucho más robusto tener todos los cerebros en el servidor .
2. Programación Orientada a Objetos.
Me doy cuenta de que esto es un tema controvertido, pero no creo que la programación orientada a objetos sea algo tan importante. Creo que es un buen modelo 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 de las grandes empresas le gusta la programación orientada a objetos es porque produce mucho trabajo. Algo que podría representarse naturalmente como, por ejemplo, una lista de números 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 proporcionan algunos de los efectos de las funciones de primera clase. Pero esto no es novedad para los programadores de Lisp. Cuando se tienen funciones de primera clase reales, se pueden utilizar de cualquier forma que sea apropiada para la tarea en cuestión, en lugar de forzar todo a un molde de clases y métodos.
Lo que esto significa para el diseño de lenguajes, creo, es que no se debe profundizar demasiado en la programación orientada a objetos. 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é.
Que un comité diseñe tu lenguaje es un gran escollo, y no solo por las razones que todos conocemos. Todos sabemos que los comités tienden a producir diseños irregulares e inconsistentes, pero creo que un peligro mayor es que no asuman riesgos. Cuando una persona está a cargo, puede asumir riesgos sobre los que un comité nunca estaría de acuerdo.
¿Es necesario correr riesgos para diseñar un buen lenguaje? Muchas personas podrían sospechar que el diseño de lenguajes es algo en lo que hay que ceñirse bastante a 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?