Loading...

CINCO PREGUNTAS SOBRE EL DISEÑO DE LENGUAJES

Original

Mayo 2001

(Estas son algunas notas que tomé para una discusión en panel 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 cómo las personas hablan con las computadoras. La computadora estaría igual de feliz hablando cualquier idioma 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 objetivo de los lenguajes de programación es evitar que nuestros 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 diseñar puentes. Allí tu trabajo es en gran medida una cuestión de abarcar una distancia dada con el menor material. El otro extremo del espectro es diseñar sillas. Los diseñadores de sillas tienen que pasar su tiempo pensando 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.

La mayoría de nosotros odiamos reconocer esto. Diseñar sistemas de gran elegancia matemática suena mucho más atractivo para la mayoría de nosotros que complacer 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 ser diseñados para adaptarse a las debilidades humanas, no quiero decir que los lenguajes tienen que ser diseñados para programadores malos. 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 gustaría 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 otras personas los usaran.

Cuando los lenguajes son diseñados 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 menosprecia. Cobol es el caso más extremo, pero muchos lenguajes están impregnados de este espíritu.

No tiene nada que ver con cuán abstracto es 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 programadores malos es que hay más programadores malos que buenos. Eso puede ser cierto. Pero esos pocos buenos programadores escriben un porcentaje desproporcionado del software.

Me interesa la pregunta, ¿cómo diseñas un lenguaje que les gustará a los mejores hackers? A mí me parece que esto es idéntico a la pregunta, ¿cómo diseñas un buen lenguaje de programación?, pero incluso si no lo es, al menos es una pregunta interesante.

3. Dale al Programador Tanto Control Como Sea Posible.

Muchos lenguajes (en especial 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 tanto control como puedas.

Cuando aprendí Lisp por primera vez, lo que más me gustó de él fue que me consideraba un socio igual. En los otros lenguajes que había aprendido hasta entonces, había el lenguaje y había mi programa, escrito en el lenguaje, y los dos eran muy separados. Pero en Lisp, las funciones y macros que escribía eran como aquellas que constituían el propio lenguaje. 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 es subestimada e incluso despreciada. Pero si miras en los corazones de los hackers, verás que realmente les encanta. ¿Cuántas veces has oído a hackers hablar con cariño de cómo en, digamos, APL, podían hacer cosas asombrosas con solo un par de líneas de código? Creo que cualquier cosa que realmente les encante a las personas realmente inteligentes vale la pena prestar atención.

Creo que casi cualquier cosa que puedas hacer para hacer que los programas sean más cortos es buena. Debería haber muchas funciones de biblioteca; cualquier cosa que pueda ser implícita debería serlo; la sintaxis debería ser concisa hasta el extremo; incluso los nombres de las cosas deberían ser cortos.

Y no solo los programas deberían ser cortos. El manual debería ser delgado también. Una buena parte de los manuales está ocupada con 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 Qué Es Hacking.

Mucha gente desearía que hacking fuera matemáticas, o al menos algo parecido a una ciencia natural. Creo que hacking es más como 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 estática.

Lo que a los hackers les gusta hacer es crear grandes programas. Y creo que, al menos en nuestras propias mentes, tenemos que recordar que es algo 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 incorpore 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 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 hace más que engrosar tu manual. (Los manuales de Symbolics fueron un caso en punto.) Así que creo que tendremos que trabajar en formas de organizar bibliotecas. Lo ideal sería diseñarlas de tal manera que el programador pudiera adivinar qué llamada de biblioteca haría lo correcto.

2. ¿Realmente la Gente Teme la Sintaxis Prefija?

Este es un problema abierto en el sentido de que he estado preguntándome sobre ello durante años y todavía no sé la respuesta. La sintaxis prefija me parece perfectamente natural, excepto posiblemente para las matemáticas. Pero podría ser que gran parte de la falta de popularidad de Lisp se deba simplemente a tener una sintaxis poco familiar. Si hacer algo al respecto, si es cierto, es otra pregunta.

3. ¿Qué Necesitas para Software Basado en Servidores?

Creo que muchas de las aplicaciones nuevas más emocionantes que se escriban en los próximos veinte años serán aplicaciones basadas en la Web, es decir, programas que se ejecutan en el servidor y te hablan a través de un navegador web. Y para escribir este tipo de programas puede que necesitemos algunas nuevas cosas.

Una cosa que necesitaremos es soporte para la nueva forma en que se lanzan las aplicaciones basadas en servidores. En lugar de tener una o dos grandes versiones al año, como el software de escritorio, las aplicaciones basadas en servidores se lanzan como una serie de pequeños cambios. Puedes tener hasta cinco o diez lanzamientos al día. Y como regla, todos usarán siempre la última versión.

¿Sabes cómo puedes diseñar programas para que sean depurables? Bueno, el software basado en servidores también tiene que ser diseñado para ser cambiable. Tienes que poder cambiarlo fácilmente, o al menos saber qué es un cambio pequeño y qué es uno trascendental.

Otra cosa que podría resultar útil para el software basado en servidores, sorprendentemente, son las continuaciones. En el software basado en la Web puedes usar algo como el estilo de paso de continuaciones para obtener el efecto de subrutinas en el inherentemente sin estado mundo de una sesión web. Quizás 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 es esta esperanza, pero una cosa que realmente me encantaría hacer, personalmente, es descubrir una nueva abstracción: algo que haría tanta diferencia como tener funciones de primera clase o recursión o incluso parámetros de palabra clave. Este puede ser un sueño imposible. Estas cosas no se descubren tan a menudo. Pero siempre estoy buscando.

1. Puedes Usar Cualquier Lenguaje 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 lenguaje que el sistema operativo. Y así, hace diez años, escribir software significaba prácticamente escribir software en C. Eventualmente, se desarrolló una tradición: los programas de aplicación no deben escribirse en lenguajes inusuales. Y esta tradición tuvo tanto tiempo para desarrollarse que personas no técnicas como gerentes y capitalistas de riesgo también la aprendieron.

El software basado en servidores destruye todo este modelo. Con el software basado en servidores, puedes usar cualquier lenguaje que desees. Casi nadie entiende esto todavía (especialmente no los gerentes y capitalistas de riesgo). Algunos hackers lo entienden, y por eso incluso oímos hablar de nuevos lenguajes independientes como Perl y Python. No estamos oyendo hablar de Perl y Python porque la gente los esté usando 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 Proviene de los Perfiles.

Los diseñadores de lenguajes, o al menos 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 intentado sabe que no puedes adivinar dónde están estos cuellos de botella. Los perfiles son la respuesta.

Los diseñadores de lenguajes están resolviendo el problema equivocado. Los usuarios no necesitan puntos de referencia para funcionar rápido. Lo que necesitan es un lenguaje que pueda mostrarles qué partes de sus propios programas necesitan ser reescritas. Ahí es donde proviene la velocidad en la práctica. Así que tal vez sería una ganancia neta si los implementadores de lenguajes tomaran la mitad del tiempo que habrían gastado haciendo optimizaciones de compilador y lo gastaran escribiendo 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 para la que se estaban utilizando. C fue escrito por personas que lo necesitaban para programación de sistemas. Lisp se desarrolló en parte para hacer diferenciación simbólica, y McCarthy estaba tan ansioso por comenzar 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 impulsar a tu lenguaje a tener nuevas características que los programadores necesitan. Personalmente, estoy interesado en escribir un lenguaje que sea bueno para escribir aplicaciones basadas en servidores.

[Durante el panel, Guy Steele también hizo este punto, con la sugerencia adicional de que la aplicación no debería 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 una tarea limitada. Creo que si miras a tu alrededor, encontrarás que muchos programas grandes y serios comenzaron como programas desechables. No me sorprendería si la mayoría de los programas comenzaron como programas desechables. Y así, si quieres hacer un lenguaje que sea bueno para escribir software en general, tiene que ser bueno para escribir programas desechables, porque esa es la etapa larval de la mayoría del software.

5. La Sintaxis Está Conectada a la Semántica.

Es tradicional pensar en la sintaxis y la semántica como 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.

Hablaba recientemente con Robert Morris, y él señaló que la sobrecarga de operadores es una mayor ventaja en lenguajes con sintaxis infija. En un lenguaje con sintaxis prefija, cualquier función que definas es efectivamente un operador. Si quieres definir un más para un nuevo tipo de número que has inventado, 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.

En la década de 1970 estaba de moda diseñar nuevos lenguajes de programación. Recientemente no lo ha estado. Pero creo que el software basado en servidores hará que los nuevos lenguajes vuelvan a estar de moda. Con el software basado en servidores, puedes usar cualquier lenguaje que desees, así que si alguien diseña un lenguaje que realmente parece mejor que otros que están disponibles, habrá personas que se arriesguen y lo usen.

2. Compartición de Tiempo.

Richard Kelsey dio esto como una idea cuyo momento ha llegado nuevamente en el último panel, y estoy completamente de acuerdo con él. Mi suposición (y la suposición de Microsoft, parece) es que gran parte de la computación se trasladará del escritorio a servidores remotos. En otras palabras, la compartición de tiempo ha vuelto. Y creo que tendrá que haber soporte para ello a nivel de lenguaje. Por ejemplo, sé que Richard y Jonathan Rees han hecho mucho trabajo implementando la programación de procesos dentro de Scheme 48.

3. Eficiencia.

Recientemente estaba empezando a parecer que las computadoras finalmente eran lo suficientemente rápidas. Cada vez más comenzábamos a escuchar sobre código de bytes, lo que implica al menos para mí que sentimos que tenemos ciclos de sobra. Pero no creo que lo tengamos, con el software basado en servidores. Alguien tendrá que pagar por los servidores en los que se ejecuta el software, y el número de usuarios que pueden soportar por máquina será el divisor de su costo de capital.

Así que creo que la eficiencia importará, al menos en cuellos de botella computacionales. Será especialmente importante hacer i/o rápido, porque las aplicaciones basadas en servidores hacen mucho i/o.

Puede resultar que el código de bytes no sea una ventaja, 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 en sí mismo una buena idea. Puede resultar que este todo campo de batalla sea eludido. Eso sería algo divertido.

1. Clientes.

Esto es solo una suposición, pero mi suposición es que el modelo ganador para la mayoría de las aplicaciones será puramente basado en servidores. Diseñar software que funcione bajo la suposición de que todos tendrán tu cliente es como diseñar una sociedad bajo la suposición 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 a la Web, y todo lo que podrás asumir sobre ellos es que pueden soportar html simple y formularios. ¿Tendrás un navegador en tu teléfono celular? ¿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? ¿Tu reloj? No lo sé. Y no tengo que saberlo si apuesto a que todo estará en el servidor. Es simplemente mucho más robusto tener todos los procesos 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 un gran problema. 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 de 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 las personas en grandes empresas les gusta la programación orientada a objetos es porque produce mucho de lo que parece trabajo. Algo que podría representarse naturalmente como, digamos, una lista de enteros, ahora puede representarse como una clase con todo tipo de andamiaje y bullicio.

Otro atractivo de la programación orientada a objetos es que los métodos te dan parte del efecto de 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 incorporar la programación orientada a objetos demasiado profundamente. Quizás la respuesta sea ofrecer cosas más generales y subyacentes, y dejar que las personas diseñen cualquier sistema de objetos que deseen 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 persona está a cargo, puede tomar riesgos que un comité nunca aceptaría.

¿Es necesario tomar riesgos para diseñar un buen lenguaje? Muchas personas podrían sospechar que el diseño de lenguajes es algo en lo que deberías ceñirte bastante a la sabiduría convencional. Apuesto a que esto no es cierto. En todo lo demás que las personas hacen, la recompensa es proporcional al riesgo. ¿Por qué debería ser diferente el diseño de lenguajes?