CINCO CUESTIONES ACERCA DEL DISEÑO DE LENGUAJES


Mayo 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.)


DIRECTRIZ FILOSÓFICA

1. Los Lenguajes de Programación son para las Personas.


Los lenguajes de programación son el medio a través del cuál la gente le habla a las computadoras. La computadora serí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 lidiar con el lenguaje de máquina. La idea con los lenguajes de programación es evitar que nuestros pobres y frágiles cerebros humanos sean 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 más limpios y abstractos es el diseño de puentes. Ahí, tu trabajo es en gran medida una cuestión de cruzar una distancia dada con el mínimo de material. El otro extremo del espectro se encuentra en el diseño de sillas. Los diseñadores tienen que invertir su tiempo pensando en los traseros humanos.

El software varía de la misma manera. Diseñar algoritmos para el enrutamiento de datos a través de una red es un problema agradable, abstracto, como el diseño de puentes. Mientras que diseñar lenguajes de programación es como diseñar sillas: todo es 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 rol para la elegancia matemática: algunos tipos de elegancia hacen los programas 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 me refiero a que los lenguajes tienen que ser diseñados para los malos programadores. De hecho, creo que deberías diseñar para los mejores programadores, pero incluso los mejores programadores tienen sus limitaciones. No creo que alguien quiera 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 nos fijamos en la historia de los lenguajes de programación, muchos de los mejores fueron diseñados para ser usados por sus propios autores, y muchos de los peores han sido diseñados para que otras personas los usaran.

Cuando los lenguajes están diseñados para otras personas, siempre es un grupo específico de personas: gente no tan inteligente como el diseñador del lenguaje. Así, tienes un lenguaje que es condescendiente contigo. Cobol es el caso más extremo, pero una gran cantidad de lenguajes están impregnados de este espíritu.

No tiene nada que ver con que tan abstracto sea el lenguaje. C es de muy bajo nivel, pero fue diseñado para ser utilizado por sus autores, y es por eso que le gusta a los hackers. [a]

El argumento para diseñar lenguajes para los malos programadores es que hay más malos que buenos programadores. Puede que sea así. Pero los buenos programadores escriben un porcentaje desproporcionalmente grande de los programas.

Estoy interesado en la pregunta, ¿cómo diseñar un lenguaje que le guste a los mejores hackers? Se me ocurre pensar que esto es idéntico a la pregunta, ¿cómo diseñar un buen lenguaje de programación?, pero incluso si no lo es, por lo menos es una pregunta interesante.
 

3. Da al Programador Tanto Control Como sea Posible.


Muchos lenguajes (en especial los diseñados para otras personas) tienen la actitud de una institutriz: tratan de evitar que hagas cosas que creen no son buenas para ti. Me gusta el enfoque opuesto: da al programador tanto control como sea posible.

Cuando aprendí Lisp, lo que más me gustó fue que me consideraba un socio en igualdad de condiciones. En los demás lenguajes que había aprendido hasta entonces, estaba el lenguaje y estaba mi programa, escrito en el lenguaje, y los dos eran muy diferentes. Sin embargo, en Lisp las funciones y macros que escribí eran como las que integraban el propio lenguaje. Podría reescribir el lenguaje si quería. Tenía el mismo atractivo que el software libre.
 

4. Apunta a la Brevedad.

 
La brevedad es subestimada y despreciada incluso. Pero si buscaras en los corazones de los hackers, verías que realmente la aman. ¿Cuántas veces has escuchado a los hackers hablar con cariño de como en, por ejemplo, APL, pueden hacer cosas increíbles con sólo un par de líneas de código? Creo que vale la pena prestarle atención a cualquier cosa que la gente realmente inteligente ame.

Pienso que casi cualquier cosa que puedas hacer para que los programas sean más cortos es buena. Debe haber muchas funciones de biblioteca; cualquier cosa que pueda ser implícita debe serlo; la sintaxis debe ser concisa al extremo; incluso los nombres de las cosas deben ser cortos.

Y no sólo los programas deben ser cortos. El manual debe ser fino también. Una buena cantidad de manuales esta tomada por 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 mucha explicación.
 

5. Admite lo que es Hackear.


Mucha gente desea que hackear fueran matemáticas, o al menos algo así como una ciencia natural. Creo que hackear es más parecido a la arquitectura. La arquitectura se relaciona 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 edificios grandiosos, no descubrimientos acerca de la estática.

Lo que les gusta a los hackers es hacer buenos programas. Y creo que, al menos en nuestra mente, tenemos que recordar que es una cosa admirable escribir programas grandiosos, aun cuando este trabajo no se traduzca fácilmente a la moneda intelectual convencional de los articulos sobre trabajos de investigación. Intelectualmente, es tan valioso diseñar un lenguaje que amen los programadores como lo es diseñar uno horrible que encarna una cierta idea sobre la que podrías publicar un artículo.


 

PROBLEMAS ABIERTOS

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 haciendo cada vez más grandes, y esto puede ser peligroso. Si se tarda más en encontrar la función de biblioteca que hará lo que deseas de lo que te tomaría escribirla tú mismo, entonces todo ese código no está haciendo nada más que engrosar tu manual. (Los manuales Symbolics eran un ejemplo de ello.) Así que creo que tendremos que trabajar en formas de organizar las bibliotecas. Lo ideal sería diseñarlas para que el programador pueda adivinar que llamada a biblioteca hará lo correcto.
 

2. ¿La Sintaxis de Prefijo Asusta Realmente a las Personas?


Este es un problema abierto en el sentido de que me he preguntado al respecto durante años y todavía no conozco la respuesta. La sintaxis de prefijo me parece perfectamente natural, con la posible excepción de su uso en matemáticas. Pero podría ser que una gran cantidad de la impopularidad de Lisp sea simplemente debida a que tiene una sintaxis poco familiar. Hacer algo al respecto, si esto resulta cierto, es otra cuestión.
 

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


Creo que muchas de las nuevas aplicaciones más interesantes que se escribirán en los próximos veinte años serán aplicaciones basadas en Web, es decir, programas instalados en el servidor y que se comunican contigo a través de un navegador Web. Y es posible que para escribir este tipo de programas necesitemos algunas cosas nuevas.

Una cosa que vamos a necesitar es soporte, por la nueva forma en que las aplicaciones basadas en servidor son liberadas. En lugar de tener uno o dos grandes estrenos al año, como en el software de escritorio, las aplicaciones basadas en servidor se liberan como una serie de pequeños cambios. Puedes tener hasta cinco o diez versiones al día. Y como regla todo el mundo utilizara siempre la última versión.

¿Sabes diseñar programas que sean depurables? Bueno, el software basado en servidor tiene también que ser diseñado para ser modificado. Tienes que ser capaz de cambiarlo fácilmente, o por lo menos saber cual cambio es pequeño y cual es trascendental.

Sorprendentemente, otra cosa que podría llegar a ser útil para el software basado en servidor son las continuaciones. En software basado en Web puedes usar algo como el estilo de continuación de paso [a] para conseguir 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 esto no fuera demasiado costoso.

 

4. ¿Qué Nuevas Abstracciones nos Quedan por Descubrir?


No estoy seguro que tan razonable sea esta esperanza, pero una cosa que me gustaría hacer, personalmente, es descubrir una nueva abstracción: algo que hiciera tanta diferencia como tener funciones de primera clase o recursividad o incluso parámetros de palabras clave. Puede que este sea un sueño imposible. Estas cosas no se descubren tan a menudo. Pero siempre estoy buscando.


 

SECRETOS POCO CONOCIDOS

1. Puedes Usar Cualquier Lenguaje que Desees.


Escribir programas de aplicaciones solía significar escribir software de escritorio. Y en el software de escritorio existe una tendencia importante hacia la escritura de la aplicación en el mismo lenguaje que el sistema operativo. Así, hace diez años, escribir software más o menos significaba escribir en C. Eventualmente se desarrolló una tradición: los programas de aplicaciones no deben ser escritos en lenguajes poco comunes. Y esta tradición tuvo tanto tiempo para desarrollarse que personas no técnicas, como los gerentes y los capitalistas de riesgo también la aprendieron.

El software basado en servidor destruye todo este modelo. Con software basado en servidor puedes utilizar cualquier lenguaje que desees. Casi nadie entiende esto todavía (en especial, no los gerentes ni los capitalistas de riesgo). Unos pocos hackers lo entienden, y es por eso que apenas escuchamos hablar de nuevos lenguajes, como Perl y Python. No estamos escuchando hablar de Perl y Python porque la gente los use 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 hay potencialmente una audiencia real para nuestro trabajo.

 

2. La Velocidad Viene de los Perfiladores.


A los diseñadores del lenguaje, o por lo menos a quienes los implementan, les gusta escribir compiladores que generen código rápido. Pero yo no creo que sea esto lo que hace a los lenguajes rápidos para los usuarios. Knuth [c] señaló hace mucho tiempo que la velocidad sólo importa en unos pocos cuellos de botella críticos. Y cualquiera que lo haya intentado 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 puntos de referencia para correr rápido. Lo que necesitan es un lenguaje que pueda mostrarles qué partes de sus propios programas necesitan ser reescritos. Ahí es de donde proviene la velocidad en la práctica. Así que tal vez sería una ganancia neta si los implementadores del lenguaje se tomaran la mitad del tiempo que gastaron haciendo las optimizaciones del compilador y en su lugar lo invirtieran escribiendo un buen perfilador.

 

3. Necesitas una Aplicación Para Impulsar el Diseño de un Lenguaje.


Puede que esta no sea una regla absoluta, pero parece que los mejores lenguajes evolucionaron juntos con alguna aplicación que los estaba utilizando para ser escrita. C fue escrito por gente que lo necesitaba para programación de sistemas. Lisp fue desarrollado en parte para hacer diferenciación simbólica, y McCarthy estaba tan ansioso por empezar, que ya estaba escribiendo programas de diferenciación incluso en el primer documento sobre Lisp, en 1960.

Es especialmente bueno si tu aplicación resuelve un nuevo problema. Eso tendera a impulsar a que tu lenguaje tenga nuevas funciones que los programadores necesiten. En lo personal, estoy interesado en escribir un lenguaje que sea bueno para escribir aplicaciones basadas en servidor.

[Durante el panel, Guy Steele [d] también mencionó 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 este 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 miraras a tu alrededor encontrarías que muchos programas grandes, serios, comenzaron como programas desechables. No me sorprendería si la mayoría de los programas iniciaron como desechables. Así que si quieres hacer un lenguaje que sea bueno para escribir software en general, tiene que ser bueno para escribir programas desechables, ya que esa es la fase larvaria de la mayoría del software.
 

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


Es común pensar en la sintaxis y la semántica como completamente independientes. Esto puede sonar chocante, pero puede que no lo sean. Creo que lo que quieres en tu lenguaje puede estar relacionado a cómo lo expresas.

Recientemente estuve hablando con Robert Morris [e], y señaló que la sobrecarga del operador es más exitosa en lenguajes con sintaxis infija. En un lenguaje con sintaxis de prefijo, cualquier función que se define es efectivamente un operador. Si deseas definir un extra a favor de un nuevo tipo de número que has hecho, puedes simplemente definir una nueva función para agregarlos. Si haces eso en un lenguaje con sintaxis infija, hay una gran diferencia de aspecto entre el uso de un operador sobrecargado y una llamada a función.


 

IDEAS CUYO TIEMPO HA REGRESADO

1. Nuevos Lenguajes de Programación.


En la década de 1970 estaba de moda diseñar nuevos lenguajes de programación. Últimamente esto ha dejado de ser asi. Pero creo que el software basado en servidor hará que los nuevos lenguajes se pongan de moda otra vez. Con software basado en servidor puedes utilizar cualquier lenguaje que desees, así que si alguien diseña un lenguaje que en realidad parezca mejor a otros disponibles, habrá personas que correrán el riesgo y lo utilizarán.

 

2. Tiempo Compartido.


En el último panel, Richard Kelsey mencionó ésta como una idea cuyo tiempo ha regresado, y estoy completamente de acuerdo con él. Mi opinión (y, por lo que parece, supongo que la de Microsoft también) es que mucha de la computación se moverá del escritorio a servidores remotos. En otras palabras, el tiempo compartido está de vuelta. Y creo que necesitara haber soporte a nivel de lenguaje. Por ejemplo, sé que Richard y Jonathan Rees han hecho mucho trabajo implementando programación de procesos en esquema 48.

 

3. Eficiencia.


Recientemente empezaba a parecer que las computadoras eran finalmente lo suficientemente rápidas. Cada vez más, se empezaba a oír hablar de código de bytes, lo que implica, al menos para mí, que sentimos que tenemos ciclos por ahorrarnos. Pero con software basado en servidor no creo que lo haremos. Alguien tendrá que pagar por los servidores en que el software se ejecuta, y el número de usuarios que pueden soportar por cada máquina sera el divisor de su costo capital.

Así que creo que la eficiencia sera importante, al menos en los cuellos de botella computacionales. Será especialmente importante hacer I/O rápido, por que las aplicaciones basadas en servidor hacen mucho I/O.

Puede resultar que a fin de cuentas el código de bytes no sea una ganancia. Por el momento Sun y Microsoft parecen estar frente a frente en una especie de batalla de los códigos de bytes. 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 todo este campo de batalla se anule. Eso sería divertido.


 

ESCOLLOS Y TRAMPAS

1. Clientes.


Esta es sólo una suposición, pero mi conjetura es que el modelo de éxito para la mayoría de las aplicaciones será estar basadas puramente en servidor. Diseñar software que funciona en el supuesto de que todos tendrán tu cliente es como diseñar una sociedad en el supuesto de que todo el mundo sera honesto. Sin duda, sería conveniente, pero tienes que asumir que nunca sucederá.

Creo que habrá una proliferación de dispositivos que tendrán algún tipo de acceso a Internet, y todo lo que podrás asumir de ellos es que podrán soportar html y formas simples. ¿Tendrás un navegador en tu teléfono celular? ¿Habrá un teléfono en tu Palm Pilot? ¿Tendrá tu Blackberry una pantalla más grande? ¿Podrás navegar por la Web en tu Gameboy? ¿En tu reloj? No lo sé. Y no hace falta saber si tan solo apuesto a que todo estara en el servidor. Es simplemente que es mucho más robusto tener todos los cerebros en el servidor.
 

2. Programación Orientada a Objetos.


Comprendo que este es un tema polémico, pero no creo que la programación orientada a objetos sea una cosa muy importante. Creo que es un buen modelo para cierto tipo de aplicaciones que necesitan ese tipo específico de estructura de datos, como los sistemas de Windows, simulaciones y programas CAD. Pero no veo por qué deba 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 se debe a que arroja mucho de lo que parece trabajo. Por ejemplo, algo que naturalmente sería representado como una lista de números enteros, ahora puede ser representada como una clase, con todo tipo de florituras.

Otro de los atractivos de la programación orientada a objetos es que los métodos dan algunos de los efectos de las funciones de primera clase. Pero esto es noticia vieja para los programadores Lisp. Cuando tienes funciones reales de primera clase, puedes simplemente utilizarlas en cualquier forma que sea apropiada para la tarea en cuestión, en vez de forzar todo en un molde de clases y métodos.

Lo que esto significa para el diseño de lenguajes, creo yo, es que no se debe construir programación orientada a objetos con demasiada profundidad. Tal vez la respuesta es ofrecer cosas mas fundamentales y generales, y dejar que la gente diseñe cualquier sistema de objetos que quieran como bibliotecas.
 

3. Diseño por Comité.


Diseñar tu lenguaje por comité es un gran error, y no sólo por las razones que todos conocen. Todo el mundo sabe que los comités tienden a producir diseños inconsistentes e incomodos. Pero creo que el peligro mayor es que no asumen riesgos. Cuando una sola persona esta a cargo puede tomar riesgos que un comité nunca aprobaría.

Sin embargo, ¿es necesario tomar riesgos para diseñar un buen lenguaje? Mucha gente podría suponer que el diseño de lenguajes es algo que debe apegarse 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é debería el diseño de lenguajes ser diferente?





Traducido de Five Questions about Lenguaje Design por Paul Graham. Traducción: Armando Alvarez.


 

Notas del Traductor:


[a] En La Palabra “Hacker” Paul Graham nos da una buena descripción del sentido en que hay que entender la palabra en este contexto: “Para la prensa popular hacker significa alguien que irrumpe en las computadoras. Entre los programadores significa: un buen programador. Pero los dos sentidos están conectados. Para los programadores hacker connota dominio en el sentido más literal: alguien que puede hacer que una computadora haga lo que él quiere—ya sea que la computadora quiera o no.”

[b] En la programación funcional, el estilo de continuación de paso (Continuation-passing style o CPS por sus siglas en inglés) es un estilo de programación en el que se pasa el control de forma explícita en la forma de una continuación. Gerald Jay Sussman y Guy L. Steele Jr., acuñaron la frase en el Memo AI 349 (1975), que establece la primera versión del lenguaje de programación Scheme.

En lugar de "devolver" los valores como en el estilo directo, más familiar, una función escrita en el estilo de la continuación de paso, toma un argumento explícito de "continuación", es decir, una función destinada a recibir el resultado del cálculo realizado dentro de la función original. Del mismo modo, cuando una subrutina se invoca dentro de una función de CPS, la función de llamada está obligada a suministrar un procedimiento que se invoca con el valor "return" de la subrutina. Expresar el código de esta forma hace una serie de cosas explícitas que están implícitas en el estilo directo. Estas incluyen: resultados del procedimiento, que se manifiestan como llamadas a una continuación; valores intermedios, los cuales son todos nombres dados; orden de evaluación del argumento, que se hace explícito; y llamadas a cola, que es simplemente llamar a un procedimiento con la misma continuación que fue pasada al que hace la llamada, sin modificar. [Traducido de Continuation-passing style. Fuente: Wikipedia en Inglés. Ver]

[c] Donald Ervin Knuth, (nacido el 10 de enero de 1938 en Milwaukee, Wisconsin) es uno de los más reconocidos expertos en ciencias de la computación por su seminal investigación dentro del análisis de algoritmos y compiladores. Es Profesor Emérito de la Universidad de Stanford.

Se le conoce principalmente por ser el autor de la obra The Art of Computer Programming (El Arte de Programar Computadoras), una de las más respetadas referencias en el campo de las ciencias de la computación. Sentó las bases y dio nombre al análisis de algoritmos, y ha realizado numerosos aportes a varias ramas teóricas de la informática. Es el creador de TEX, del sistema de diseño de tipos METAFONT y del estilo de programación conocido como programación literaria (Literate programming). [Fuente: Wikipedia. Ver]

[d] Guy L. Steele desarrolló junto a Gerald Jay Sussman el lenguaje de programación Scheme en la decada de los setenta.

[e] Robert Tappan Morris (tambien conocido como rtm) nació en 1965 y es profesor asociado en el Instituto Tecnológico de Massachussets en el departamento de Ingeniería Electrónica y Ciencias de la Computación. Es conocido por crear el Gusano Morris en 1988, considerado como el primer gusano de ordenador de la era de Internet. Es hijo de Robert Morris, ex jefe científico en el Centro Nacional de Seguridad Informática, una división de la agencia de Seguridad Nacional (NSA). [Fuente: Wikipedia Ver]