SIENDO POPULAR
Mayo 2001
(Este artículo fue escrito como una especie de plan de negocios para un nuevo lenguaje. Por lo tanto, le falta (porque se da por supuesto) la característica más importante de un buen lenguaje de programación: abstracciones muy potentes.)
Un amigo mío le dijo una vez a un eminente experto en sistemas operativos que quería diseñar un lenguaje de programación realmente bueno. El experto le dijo que sería una pérdida de tiempo, que los lenguajes de programación no se hacen populares o impopulares sobre la base de sus méritos, y por tanto no importaría que tan bueno fuera su lenguaje, nadie lo usaría. Al menos, eso era lo que había sucedido con el lenguaje que él había diseñado.
¿Qué hace popular a un lenguaje? ¿Merecen los lenguajes populares su popularidad? ¿Vale la pena tratar de definir un buen lenguaje de programación? ¿Cómo lo harías?
Creo que las respuestas a estas preguntas se pueden encontrar observando a los hackers [a], y averiguando que quieren. Los lenguajes de programación son para los hackers, y un lenguaje de programación es bueno como lenguaje de programación (en lugar de, digamos, como ejercicio de semántica denotacional o diseño de compiladores) si y sólo si a los hackers les gusta.
1 La Mecánica de la Popularidad
Es cierto, sin duda, que la mayoría de la gente no elige los lenguajes de programación simplemente en base a sus méritos. A la mayoría de los programadores otra persona les dice qué lenguaje utilizar. Y, sin embargo, creo que el efecto de tales factores externos sobre la popularidad de los lenguajes de programación no es tan grande como a veces se piensa. Creo que un problema más grande es que la idea que un hacker tiene sobre lo que constituye un buen lenguaje de programación no es la misma que tienen la mayoría de los diseñadores del lenguaje.
Entre las dos, la opinión de los hackers es la que importa. Los lenguajes de programación no son teoremas. Son herramientas, diseñadas para la gente, y tienen que ser diseñadas para adaptarse a las fortalezas y debilidades humanas tanto como los zapatos tienen que ser diseñados para los pies humanos. Si un zapato pincha cuando te lo pones, es un mal zapato, por muy elegante que pueda ser como obra escultórica.
Puede ser que la mayoría de los programadores no distingan un buen lenguaje de uno malo. Pero eso no es diferente con cualquier otra herramienta. Esto no quiere decir que sea una pérdida de tiempo tratar de diseñar un buen lenguaje. Los hackers expertos reconocen un buen lenguaje cuando lo ven, y lo utilizaran. Es cierto, son una pequeña minoría, pero esa pequeña minoría escribe todos los programas buenos, y su influencia es tal que el resto de los programadores tienden a utilizar el lenguaje que utilizan. A menudo, de hecho, no es sólo influencia, sino ordenes: con frecuencia los hackers expertos son las mismas personas que, como jefes o consejeros en la facultad, le dicen a otros programadores que lenguaje utilizar.
La opinión de los hackers expertos no es la única fuerza que determina la relativa popularidad de los lenguajes de programación —software heredado (Cobol) y productos mediáticos (Ada, Java) también juegan un papel— pero creo que es la fuerza más poderosa en el largo plazo. Dada una masa crítica inicial y el tiempo suficiente, un lenguaje de programación probablemente se haga tan popular como lo merece. Y la popularidad separa aún más a los buenos lenguajes de los malos, porque la retroalimentación de los usuarios reales siempre da lugar a mejoras. Observa cuanto ha cambiado en su vida cualquier lenguaje popular. Perl y Fortran son casos extremos, pero incluso Lisp ha cambiado mucho. Por ejemplo, Lisp 1.5 no tenia macros; estas evolucionaron más tarde, después que los hackers del MIT [b] habían pasado un par de años utilizando Lisp para escribir programas reales. [1]
Sea o no que un lenguaje tenga que ser bueno para ser popular, creo que un lenguaje tiene que ser popular para ser bueno. Y tiene que permanecer popular para mantenerse bueno. La evolución en lenguajes de programación no se detiene. Y sin embargo, las versiones de Lisp que tenemos hoy en día siguen siendo más o menos lo que había en el MIT a mediados de los 80s, porque esa fue la última vez que Lisp tuvo una base de usuarios lo suficientemente grande y exigente.
Por supuesto, los hackers tienen que saber acerca de un lenguaje antes de poder usarlo. ¿Cómo van a saberlo? De otros hackers. Pero tiene que haber al menos un grupo inicial de hackers utilizando el lenguaje para que otros escuchen hablar de ello. Me pregunto que tan grande tiene que ser este grupo; ¿cuantos usuarios conforman una masa crítica? De entrada, diría que veinte. Si un lenguaje tiene veinte usuarios distintos, es decir, veinte usuarios que decidieron usarlo por su cuenta, lo consideraría algo real.
Llegar ahí no es fácil. No me sorprendería si es más difícil ir de cero a veinte que de veinte a mil. Probablemente la mejor manera de conseguir esos veinte primeros usuarios sea utilizando un caballo de Troya: dar a la gente una aplicación que quiere, que sucede estar escrita en el nuevo lenguaje.
2 Factores Externos
Empecemos reconociendo un factor externo que afecta a la popularidad de un lenguaje de programación. Para llegar a ser popular, un lenguaje de programación tiene que ser el lenguaje de escritura de un sistema popular. Fortran y Cobol fueron los lenguajes de escritura de los primeros mainframes de IBM. C era el lenguaje de escritura de Unix, igual fue, más tarde, Perl. TCL es el lenguaje de escritura de Tk. Java y Javascript están destinados a ser los lenguajes de escritura de los navegadores web.
Lisp no es un lenguaje enormemente popular, ya que no es el lenguaje de escritura de un sistema enormemente popular. La popularidad que conserva se remonta a los años 60s y 70s, cuando era el lenguaje de escritura del MIT. Muchos de los grandes programadores de la época estuvieron asociados con el MIT en algún momento. Y a principios de los 70s, antes de C, el dialecto de Lisp del MIT, llamado MacLisp era uno de los pocos lenguajes de programación que un hacker serio querria utilizar.
Hoy Lisp es el lenguaje de escritura de dos sistemas relativamente populares, Emacs y Autocad, y sospecho que por eso la mayoría de la programación Lisp que se hace hoy en día se realiza en Emacs Lisp o AutoLisp.
Los lenguajes de programación no existen de manera aislada. Hackear es un verbo transitivo —los hackers usualmente están hackeando algo— y en la práctica los lenguajes son juzgados en relación con lo que suelen hackear. Así que si quieres diseñar un lenguaje popular, o provees más que un lenguaje, o diseñas tu lenguaje para sustituir el lenguaje de escritura de algún sistema existente.
Common Lisp es impopular en parte porque es un huérfano. Originalmente llegó con un sistema para hackear: la Máquina Lisp. Sin embargo, las maquinas Lisp (junto con las computadoras paralelas) fueron avasalladas por el creciente poder de los procesadores de propósito general en la década de 1980. Common Lisp podría haber mantenido su popularidad si hubiera sido un buen lenguaje de programación para Unix. Es, por desgracia, atrozmente malo.
Una forma de describir esta situación es decir que un lenguaje no es juzgado por sus propios méritos. Otra forma de verlo es que un lenguaje de programación realmente no es un lenguaje de programación a menos que sea también el lenguaje de escritura de algo. Esto sólo parece injusto si llega de sorpresa. Creo que no es más injusto que esperar que un lenguaje de programación tenga, por ejemplo, una implementación. Es sólo parte de lo que es un lenguaje de programación.
Un lenguaje de programación necesita una buena implementación, por supuesto, y esta debe ser gratuita. Las empresas pagan por el software, pero los hackers individuales no, y son los hackers a los que necesitas atraer.
Un lenguaje también necesita tener su propio libro. El libro debe ser delgado, bien escrito y lleno de buenos ejemplos. K&R es el ideal aquí. De momento, casi diría que un lenguaje tiene que tener un libro publicado por O'Reilly. Esa se está convirtiendo en la prueba de importancia para los hackers.
También debe haber documentación en línea. De hecho, el libro puede comenzar como documentación en línea. Pero no creo que los libros físicos estén pasados de moda todavía. Su formato es conveniente, y la censura de facto impuesta por los editores es un filtro útil, si bien imperfecto. Las librerías son uno de los lugares más importantes para el aprendizaje de nuevos lenguajes.
Lisp no es un lenguaje enormemente popular, ya que no es el lenguaje de escritura de un sistema enormemente popular. La popularidad que conserva se remonta a los años 60s y 70s, cuando era el lenguaje de escritura del MIT. Muchos de los grandes programadores de la época estuvieron asociados con el MIT en algún momento. Y a principios de los 70s, antes de C, el dialecto de Lisp del MIT, llamado MacLisp era uno de los pocos lenguajes de programación que un hacker serio querria utilizar.
Hoy Lisp es el lenguaje de escritura de dos sistemas relativamente populares, Emacs y Autocad, y sospecho que por eso la mayoría de la programación Lisp que se hace hoy en día se realiza en Emacs Lisp o AutoLisp.
Los lenguajes de programación no existen de manera aislada. Hackear es un verbo transitivo —los hackers usualmente están hackeando algo— y en la práctica los lenguajes son juzgados en relación con lo que suelen hackear. Así que si quieres diseñar un lenguaje popular, o provees más que un lenguaje, o diseñas tu lenguaje para sustituir el lenguaje de escritura de algún sistema existente.
Common Lisp es impopular en parte porque es un huérfano. Originalmente llegó con un sistema para hackear: la Máquina Lisp. Sin embargo, las maquinas Lisp (junto con las computadoras paralelas) fueron avasalladas por el creciente poder de los procesadores de propósito general en la década de 1980. Common Lisp podría haber mantenido su popularidad si hubiera sido un buen lenguaje de programación para Unix. Es, por desgracia, atrozmente malo.
Una forma de describir esta situación es decir que un lenguaje no es juzgado por sus propios méritos. Otra forma de verlo es que un lenguaje de programación realmente no es un lenguaje de programación a menos que sea también el lenguaje de escritura de algo. Esto sólo parece injusto si llega de sorpresa. Creo que no es más injusto que esperar que un lenguaje de programación tenga, por ejemplo, una implementación. Es sólo parte de lo que es un lenguaje de programación.
Un lenguaje de programación necesita una buena implementación, por supuesto, y esta debe ser gratuita. Las empresas pagan por el software, pero los hackers individuales no, y son los hackers a los que necesitas atraer.
Un lenguaje también necesita tener su propio libro. El libro debe ser delgado, bien escrito y lleno de buenos ejemplos. K&R es el ideal aquí. De momento, casi diría que un lenguaje tiene que tener un libro publicado por O'Reilly. Esa se está convirtiendo en la prueba de importancia para los hackers.
También debe haber documentación en línea. De hecho, el libro puede comenzar como documentación en línea. Pero no creo que los libros físicos estén pasados de moda todavía. Su formato es conveniente, y la censura de facto impuesta por los editores es un filtro útil, si bien imperfecto. Las librerías son uno de los lugares más importantes para el aprendizaje de nuevos lenguajes.
3 Concisión
Suponiendo que puedas proporcionar las tres cosas que necesita cualquier lenguaje —una implementación gratuita, un libro, y algo para hackear— ¿cómo haces un lenguaje que le guste a los hackers?
Una cosa que le gusta a los hackers es la concisión. Los hackers son perezosos, en la misma forma que los matemáticos y los arquitectos modernistas son perezosos: odian cualquier cosa extraña. No estaría lejos de la verdad decir que un hacker a punto de escribir un programa decide qué lenguaje utilizar, al menos inconscientemente, en base al número total de caracteres que tendrá que teclear. Si bien, esta no es precisamente la forma en que los hackers piensan, un diseñador de lenguaje haría bien en actuar como si lo fuera.
Es un error tratar como niño al usuario con expresiones tediosamente largas destinadas a asemejarse al Inglés. Cobol es notorio por este defecto. Un hacker podría considerar el que se le pida escribir:
suma x a y con resultado z
en lugar de
z = x + y
como algo entre un insulto a su inteligencia y un pecado contra Dios.
Se ha dicho en ocasiones que Lisp debería usar
La concisión es un lugar donde los lenguajes con muchos caracteres pierden. Todas las cosas en igualdad de condiciones, nadie quiere iniciar un programa con un montón de declaraciones. Cualquier cosa que pueda ser implícita, debe serlo.
Los elementos individuales deben ser breves también. Perl y Common Lisp ocupan polos opuestos en este sentido. Los programas de Perl pueden ser casi crípticamente densos, mientras que los nombres de los operadores de una función de Common Lisp son cómicamente largos. Los diseñadores de Common Lisp probablemente esperaban que los usuarios tuvieran editores de texto que escribirían estos largos nombres por ellos. Pero el costo de un nombre largo no es sólo el costo de escribirlo. También está el costo de leerlo, y el costo del espacio que ocupa en la pantalla.
Una cosa que le gusta a los hackers es la concisión. Los hackers son perezosos, en la misma forma que los matemáticos y los arquitectos modernistas son perezosos: odian cualquier cosa extraña. No estaría lejos de la verdad decir que un hacker a punto de escribir un programa decide qué lenguaje utilizar, al menos inconscientemente, en base al número total de caracteres que tendrá que teclear. Si bien, esta no es precisamente la forma en que los hackers piensan, un diseñador de lenguaje haría bien en actuar como si lo fuera.
Es un error tratar como niño al usuario con expresiones tediosamente largas destinadas a asemejarse al Inglés. Cobol es notorio por este defecto. Un hacker podría considerar el que se le pida escribir:
suma x a y con resultado z
en lugar de
z = x + y
como algo entre un insulto a su inteligencia y un pecado contra Dios.
Se ha dicho en ocasiones que Lisp debería usar
first
y rest
en lugar de car
y cdr
, porque haría que los programas fueran más fáciles de leer. Tal vez por el primer par de horas. Sin embargo, un hacker puede aprender con la suficiente rapidez que car
significa el primer elemento de una lista y cdr
significa el resto. Utilizar first
y rest
significa teclear un 50% más. Y también son de diferentes longitudes, lo que significa que los argumentos no se alinean cuando se les llama, como con frecuencia lo están car
y cdr
, en líneas sucesivas. He encontrado que es muy importante la forma como el código se alinea en la página. Apenas si puedo leer código Lisp cuando esta ajustado a una fuente de ancho variable, y mis amigos dicen que esto es cierto para otros lenguajes también.La concisión es un lugar donde los lenguajes con muchos caracteres pierden. Todas las cosas en igualdad de condiciones, nadie quiere iniciar un programa con un montón de declaraciones. Cualquier cosa que pueda ser implícita, debe serlo.
Los elementos individuales deben ser breves también. Perl y Common Lisp ocupan polos opuestos en este sentido. Los programas de Perl pueden ser casi crípticamente densos, mientras que los nombres de los operadores de una función de Common Lisp son cómicamente largos. Los diseñadores de Common Lisp probablemente esperaban que los usuarios tuvieran editores de texto que escribirían estos largos nombres por ellos. Pero el costo de un nombre largo no es sólo el costo de escribirlo. También está el costo de leerlo, y el costo del espacio que ocupa en la pantalla.
4 Posibilidad de Hackearlo
Hay una cosa más importante que la concisión para un hacker: poder hacer lo que quiera. En la historia de los lenguajes de programación una sorprendente cantidad de esfuerzos se centraron en prevenir que los programadores hicieran cosas consideradas inadecuadas. Este es un plan peligrosamente presuntuoso. ¿Cómo puede el diseñador del lenguaje saber lo que el programador necesitara hacer? Creo que los diseñadores de lenguajes harían mejor considerando que su usuario final es un genio que tendrá que hacer cosas que nunca hubieran imaginado, en lugar de un torpe que necesita ser protegido de sí mismo. El torpe se pegara un tiro en el pie de todos modos. Puedes salvarlo de remitirse a las variables en otro paquete, pero no puedes salvarlo de escribir un programa mal diseñado para resolver el problema equivocado, y tomarse una eternidad para hacerlo.
Los buenos programadores a menudo quieren hacer cosas peligrosas y desagradables. Por desagradables quiero decir cosas que van detrás de cualquier fachada semántica que el lenguaje está tratando de presentar: apoderarse de la representación interna de una abstracción de alto nivel, por ejemplo. A los hackers les gusta hackear, y hackear significa meterse en las cosas y cuestionar lo que pensaba el diseñador original.
Permitete ser cuestionado. Cuando haces cualquier herramienta, la gente la usa de formas que no esperabas, y esto es especialmente cierto de una herramienta altamente articulada como un lenguaje de programación. Más de un hacker querrá modificar tu modelo semántico de una forma que nunca hubieras imaginado. Yo digo: déjalos; da al programador acceso a tantas cosas internas como puedas sin poner en peligro los sistemas de tiempo de ejecución como el recolector de basura.
En Common Lisp a menudo he deseado iterar a través de los campos de una estructura— para limpiar referencias a un objeto eliminado, por ejemplo, o encontrar campos que están sin inicializar. Sé que las estructuras sólo son vectores por debajo. Y sin embargo no puedo escribir una función de propósito general que pueda llamar en cualquier estructura. Sólo puedo acceder a los campos por su nombre, porque eso es lo que se supone que significa una estructura.
Puede que un hacker sólo quiera subvertir el modelo previsto de las cosas una o dos veces en un programa grande. Pero, ¡qué diferencia hace ser capaz de hacerlo! Y puede ser más que una cuestión de simplemente resolver un problema. Hay una especie de placer aquí también. Los hackers comparten el placer secreto del cirujano en hurgar en las entrañas en bruto, el placer secreto del adolescente en reventar granos. [2] Para los niños, al menos, cierto tipo de horrores son fascinantes. La revista Maxim publica un volumen anual de fotografías que contienen una mezcla de fotografías de modelos y accidentes espeluznantes. Conocen su audiencia.
Históricamente, Lisp ha sido bueno para dejar que los hackers hagan las cosas a su manera. La corrección política de Common Lisp es una aberración. Los primeros Lisps te permitían meter tus manos en todo. Una buena parte de ese espíritu esta, por fortuna, preservado en las macros. Qué cosa tan maravillosa, poder hacer transformaciones arbitrarias en el código fuente.
Las macros clásicas son una verdadera herramienta de hacker— simples, potentes y peligrosas. Es tan fácil entender lo que hacen: llamas a una función con los argumentos de la macro, y lo que devuelve se inserta en el lugar de la llamada de la macro. Las macros higiénicas encarnan el principio opuesto. Tratan de protegerte de comprender lo que están haciendo. Nunca he escuchado a las macros higiénicas ser descritas en una frase. Y son un ejemplo clásico de los peligros de decidir lo que los programadores pueden esperar. Las macros higiénicas tienen por objeto protegerme de la captura de variables, entre otras cosas, pero la captura de variables es exactamente lo que quiero en algunas macros.
Un lenguaje realmente bueno debe ser tanto limpio como sucio: limpiamente diseñado, con un pequeño grupo de operadores bien entendidos y altamente ortogonales, pero sucio en el sentido de que permite a los hackers hacer lo que quieran con el mismo. C es así. Así eran los primeros Lisps. El lenguaje de un verdadero hacker siempre tendrá un carácter un poco desaliñado.
Un buen lenguaje de programación debe tener características que hacen que el tipo de personas que utilizan la frase "ingeniería de software" muevan la cabeza con desaprobación. En el otro extremo del continuum están los lenguajes como Ada y Pascal, modelos de propiedad que son buenos para la enseñanza y no mucho más.
Los buenos programadores a menudo quieren hacer cosas peligrosas y desagradables. Por desagradables quiero decir cosas que van detrás de cualquier fachada semántica que el lenguaje está tratando de presentar: apoderarse de la representación interna de una abstracción de alto nivel, por ejemplo. A los hackers les gusta hackear, y hackear significa meterse en las cosas y cuestionar lo que pensaba el diseñador original.
Permitete ser cuestionado. Cuando haces cualquier herramienta, la gente la usa de formas que no esperabas, y esto es especialmente cierto de una herramienta altamente articulada como un lenguaje de programación. Más de un hacker querrá modificar tu modelo semántico de una forma que nunca hubieras imaginado. Yo digo: déjalos; da al programador acceso a tantas cosas internas como puedas sin poner en peligro los sistemas de tiempo de ejecución como el recolector de basura.
En Common Lisp a menudo he deseado iterar a través de los campos de una estructura— para limpiar referencias a un objeto eliminado, por ejemplo, o encontrar campos que están sin inicializar. Sé que las estructuras sólo son vectores por debajo. Y sin embargo no puedo escribir una función de propósito general que pueda llamar en cualquier estructura. Sólo puedo acceder a los campos por su nombre, porque eso es lo que se supone que significa una estructura.
Puede que un hacker sólo quiera subvertir el modelo previsto de las cosas una o dos veces en un programa grande. Pero, ¡qué diferencia hace ser capaz de hacerlo! Y puede ser más que una cuestión de simplemente resolver un problema. Hay una especie de placer aquí también. Los hackers comparten el placer secreto del cirujano en hurgar en las entrañas en bruto, el placer secreto del adolescente en reventar granos. [2] Para los niños, al menos, cierto tipo de horrores son fascinantes. La revista Maxim publica un volumen anual de fotografías que contienen una mezcla de fotografías de modelos y accidentes espeluznantes. Conocen su audiencia.
Históricamente, Lisp ha sido bueno para dejar que los hackers hagan las cosas a su manera. La corrección política de Common Lisp es una aberración. Los primeros Lisps te permitían meter tus manos en todo. Una buena parte de ese espíritu esta, por fortuna, preservado en las macros. Qué cosa tan maravillosa, poder hacer transformaciones arbitrarias en el código fuente.
Las macros clásicas son una verdadera herramienta de hacker— simples, potentes y peligrosas. Es tan fácil entender lo que hacen: llamas a una función con los argumentos de la macro, y lo que devuelve se inserta en el lugar de la llamada de la macro. Las macros higiénicas encarnan el principio opuesto. Tratan de protegerte de comprender lo que están haciendo. Nunca he escuchado a las macros higiénicas ser descritas en una frase. Y son un ejemplo clásico de los peligros de decidir lo que los programadores pueden esperar. Las macros higiénicas tienen por objeto protegerme de la captura de variables, entre otras cosas, pero la captura de variables es exactamente lo que quiero en algunas macros.
Un lenguaje realmente bueno debe ser tanto limpio como sucio: limpiamente diseñado, con un pequeño grupo de operadores bien entendidos y altamente ortogonales, pero sucio en el sentido de que permite a los hackers hacer lo que quieran con el mismo. C es así. Así eran los primeros Lisps. El lenguaje de un verdadero hacker siempre tendrá un carácter un poco desaliñado.
Un buen lenguaje de programación debe tener características que hacen que el tipo de personas que utilizan la frase "ingeniería de software" muevan la cabeza con desaprobación. En el otro extremo del continuum están los lenguajes como Ada y Pascal, modelos de propiedad que son buenos para la enseñanza y no mucho más.
5 Programas Desechables
Para ser atractivo a los hackers, un lenguaje debe ser bueno para escribir los tipos de programas que quieren escribir. Y eso significa, sorprendentemente tal vez, que tiene que ser bueno para escribir programas desechables.
Un programa desechable es un programa que escribes rápidamente para una tarea limitada: un programa para automatizar algunas tareas de administración del sistema, o generar datos de prueba para una simulación, o convertir los datos de un formato a otro. Lo sorprendente de los programas desechables es que, al igual que los edificios "temporales" construidos en tantas universidades norteamericanas durante la Segunda Guerra Mundial, a menudo no se desechan. Muchos se convierten en programas reales, con características reales y usuarios reales.
Tengo el presentimiento de que los programas más grandiosos comienzan su vida de esta manera, en lugar de ser diseñados grandiosos desde el principio, como la presa Hoover. Es aterrador construir algo grande a partir de cero. Cuando las personas abordan un proyecto demasiado grande, terminan abrumadas. El proyecto, o se estanca, o el resultado es estéril y soso: un centro comercial en lugar de un verdadero centro citadino, Brasilia en lugar de Roma, Ada en lugar de C.
Otra forma de conseguir un programa grandioso es comenzar con un programa desechable y seguir mejorándolo. Este enfoque es menos desalentador, y el diseño del programa se beneficia de la evolución. Creo que, si se investigara, esta resultaría ser la forma en que se han desarrollado los programas más grandiosos. Y los que evolucionaron de esta manera probablemente están aún escritos en el lenguaje en que fueron escritos por primera vez, porque es raro que un programa sea transferido, excepto por razones políticas. Así, paradójicamente, si quieres hacer un lenguaje que sea utilizado por grandes sistemas, tienes que hacerlo bueno para escribir programas desechables, porque de ahí es de donde vienen los grandes sistemas.
Perl es un claro ejemplo de esta idea. No sólo fue diseñado para escribir programas desechables, sino que era en si mismo más o menos un programa desechable. Perl comenzó su vida como una colección de utilidades para generar informes, y sólo se convirtió en un lenguaje de programación cuando los programas desechables que la gente escribía en él se hicieron más grandes. No fue sino hasta Perl 5 (si acaso) que el lenguaje era adecuado para escribir programas serios, y sin embargo, ya era enormemente popular.
¿Que hace a un lenguaje bueno para los programas desechables? Para empezar, debe estar fácilmente disponible. Un programa desechable es algo que esperas escribir en una hora. Así que el lenguaje probablemente ya deba estar instalado en el equipo que estás utilizando. No puede ser algo que tengas que instalar antes de usarlo. Tiene que estar ahí. C estaba ahí porque venía con el sistema operativo. Perl estaba ahí porque originalmente era una herramienta para administradores de sistemas, y el tuyo ya lo tenia instalado.
Sin embargo, estar disponible significa más que estar instalado. Un lenguaje interactivo, con una interfaz de línea de comandos, es más accesible que el que tienes que compilar y ejecutar por separado. Un lenguaje de programación popular debe ser interactivo, y arrancar rápido.
Otra cosa que deseas en un programa desechable es que sea conciso. La concisión es siempre atractiva a los hackers, y más que nunca en un programa que esperan crear en una hora.
Un programa desechable es un programa que escribes rápidamente para una tarea limitada: un programa para automatizar algunas tareas de administración del sistema, o generar datos de prueba para una simulación, o convertir los datos de un formato a otro. Lo sorprendente de los programas desechables es que, al igual que los edificios "temporales" construidos en tantas universidades norteamericanas durante la Segunda Guerra Mundial, a menudo no se desechan. Muchos se convierten en programas reales, con características reales y usuarios reales.
Tengo el presentimiento de que los programas más grandiosos comienzan su vida de esta manera, en lugar de ser diseñados grandiosos desde el principio, como la presa Hoover. Es aterrador construir algo grande a partir de cero. Cuando las personas abordan un proyecto demasiado grande, terminan abrumadas. El proyecto, o se estanca, o el resultado es estéril y soso: un centro comercial en lugar de un verdadero centro citadino, Brasilia en lugar de Roma, Ada en lugar de C.
Otra forma de conseguir un programa grandioso es comenzar con un programa desechable y seguir mejorándolo. Este enfoque es menos desalentador, y el diseño del programa se beneficia de la evolución. Creo que, si se investigara, esta resultaría ser la forma en que se han desarrollado los programas más grandiosos. Y los que evolucionaron de esta manera probablemente están aún escritos en el lenguaje en que fueron escritos por primera vez, porque es raro que un programa sea transferido, excepto por razones políticas. Así, paradójicamente, si quieres hacer un lenguaje que sea utilizado por grandes sistemas, tienes que hacerlo bueno para escribir programas desechables, porque de ahí es de donde vienen los grandes sistemas.
Perl es un claro ejemplo de esta idea. No sólo fue diseñado para escribir programas desechables, sino que era en si mismo más o menos un programa desechable. Perl comenzó su vida como una colección de utilidades para generar informes, y sólo se convirtió en un lenguaje de programación cuando los programas desechables que la gente escribía en él se hicieron más grandes. No fue sino hasta Perl 5 (si acaso) que el lenguaje era adecuado para escribir programas serios, y sin embargo, ya era enormemente popular.
¿Que hace a un lenguaje bueno para los programas desechables? Para empezar, debe estar fácilmente disponible. Un programa desechable es algo que esperas escribir en una hora. Así que el lenguaje probablemente ya deba estar instalado en el equipo que estás utilizando. No puede ser algo que tengas que instalar antes de usarlo. Tiene que estar ahí. C estaba ahí porque venía con el sistema operativo. Perl estaba ahí porque originalmente era una herramienta para administradores de sistemas, y el tuyo ya lo tenia instalado.
Sin embargo, estar disponible significa más que estar instalado. Un lenguaje interactivo, con una interfaz de línea de comandos, es más accesible que el que tienes que compilar y ejecutar por separado. Un lenguaje de programación popular debe ser interactivo, y arrancar rápido.
Otra cosa que deseas en un programa desechable es que sea conciso. La concisión es siempre atractiva a los hackers, y más que nunca en un programa que esperan crear en una hora.
6 Bibliotecas
Por supuesto, lo último en brevedad es que el programa ya este escrito para ti, y simplemente llamarlo. Y esto nos lleva a lo que creo será una característica cada vez más importante de los lenguajes de programación: las funciones de biblioteca. Perl gana porque tiene grandes bibliotecas para manipular cadenas. Esta clase de funciones de biblioteca son especialmente importantes para los programas desechables, que a menudo son escritos originalmente para la conversión o la extracción de datos. Muchos programas de Perl probablemente inician como un simple par de llamadas a biblioteca pegadas.
Creo que muchos de los avances que se produzcan en los lenguajes de programación en los próximos cincuenta años tendrán que ver con las funciones de biblioteca. Creo que los futuros lenguajes de programación tendrán bibliotecas que estarán tan cuidadosamente diseñadas como el mismo lenguaje. El diseño de lenguajes de programación no será sobre si se debe hacer el lenguaje con muchos o pocos caracteres, u orientado a objetos, o funcional, o lo que sea, sino sobre como diseñar grandes bibliotecas. Los diseñadores de lenguajes a los que les gusta pensar acerca de cómo diseñar sistemas modelo pueden estremecerse ante esto. ¡Es casi como escribir aplicaciones! Es una pena. Los lenguajes son para los programadores y lo que los programadores necesitan son bibliotecas.
Es difícil diseñar buenas bibliotecas. No es simplemente una cuestión de escribir mucho código. Una vez que las bibliotecas se hacen muy grandes, a veces puede tomar más tiempo encontrar la función que necesitas que escribir el código manualmente. Las bibliotecas deben ser diseñadas usando un pequeño conjunto de operadores ortogonales, al igual que el núcleo del lenguaje. Debería ser posible para el programador adivinar que llamada a biblioteca hara lo que él necesita.
Las bibliotecas son un lugar donde Common Lisp se queda corto. Sólo hay bibliotecas rudimentarias para la manipulación de cadenas, y casi ninguna para hablar con el sistema operativo. Por razones históricas Common Lisp trata de pretender que el sistema operativo no existe. Y como no se puede hablar con el sistema operativo, es poco probable que puedas escribir un programa usando sólo los operadores integrados en Common Lisp. Tienes que usar algunos trucos específicos de aplicación también, y en la práctica, estos tienden a no darte todo lo que quieres. Los hackers tendrían en una estima más alta a Lisp si Common Lisp tuviera bibliotecas potentes para manejo de cadenas y un buen soporte del sistema operativo.
7 Sintaxis
¿Podría un lenguaje con la sintaxis de Lisp, o más precisamente, con la falta de sintaxis, volverse popular algún dia? No sé la respuesta a esta pregunta. Creo que la sintaxis no es la razón principal por la que Lisp no es popular en la actualidad. Common Lisp tiene problemas más serios que una sintaxis desconocida. Sé de varios programadores que se sienten cómodos con la sintaxis de prefijo y sin embargo usan Perl por defecto, porque cuenta con potentes cadenas de bibliotecas y puede hablar con el sistema operativo.
Hay dos posibles problemas con la notación de prefijo: que no es familiar para los programadores, y que no es lo suficientemente densa. La sabiduría convencional en el mundo Lisp sugiere que la primera es el verdadero problema. No estoy tan seguro. Sí, la notación de prefijo hace que los programadores ordinarios entren en pánico. Pero no creo que la opinión de los programadores ordinarios cuente. Los lenguajes llegan a ser populares o impopulares sobre la base de lo que los hackers expertos piensan de ellos, y creo que estos podrían lidiar con la notación de prefijo. La sintaxis de Perl puede ser bastante incomprensible, pero eso no se ha atravesado en el camino de su popularidad. Si acaso, podría haber ayudado a fomentar un culto a Perl.
Un problema más serio es el carácter difuso de la notación de prefijo. Para los hackers expertos, ese es realmente un problema. A nadie le gusta escribir
(aref a x y )
cuando podrían escribir a[x, y]
.En este caso particular hay una forma de refinar nuestra manera de salir del problema. Si tratamos a las estructuras de datos como si se tratara de funciones en los índices, podemos en su lugar escribir
(a x y )
, que es incluso más corto a como se hace en Perl. Trucos similares pueden reducir otros tipos de expresiones.Podemos deshacernos de (o hacer opcionales) una gran cantidad de paréntesis, haciendo la sangría significativa. De todos modos así es como leen el código los programadores. Cuando la sangría dice una cosa y los delimitadores dicen otra, nos guiamos por la sangría. Tratar la sangría como algo importante eliminaría esta fuente común de errores, al tiempo que ayudaría a acortar los programas.
A veces la sintaxis infija es más fácil de leer. Esto es especialmente cierto para las expresiones matemáticas. He usado Lisp durante toda mi vida de programador y todavía no encuentro a las expresiones matemáticas con prefijo como algo natural. Y sin embargo, es conveniente, sobre todo cuando se está generando código, tener operadores que acepten cualquier cantidad de argumentos. Así que si tenemos sintaxis infija, probablemente deba ser implementada como una especie de macro de lectura.
No creo que debamos oponernos religiosamente a la introducción de sintaxis en Lisp, siempre y cuando se traduzca en una via bien comprendida hacia expresiones-S subyacentes. Ya hay una buena cantidad de sintaxis en Lisp. No es necesariamente malo introducir más, siempre y cuando nadie esté obligado a usarla. En Common Lisp, algunos delimitadores están reservados para el lenguaje, lo que sugiere que al menos algunos de sus diseñadores tenían la intención de usar sintaxis en el futuro.
Una de las piezas de sintaxis más notoriamente no-lisp en Common Lisp se produce en las cadenas de formato; el formato es un lenguaje en sí mismo, y ese lenguaje no es Lisp. Si hubiera un plan para introducir más sintaxis en Lisp, los especificadores de formato podrían ser incluidos en el mismo. Sería bueno si las macros pudieran generar los especificadores de formato de la forma en que generan otro tipo de código.
Un eminente hacker de Lisp me dijo que su copia de CLTL [c] cae abierta en la sección de formato. La mía también. Esto probablemente indica margen de mejora. También puede significar que los programas hacen un montón de E/S.
8 Eficiencia
Un buen lenguaje, como todos sabemos, debe generar código rápido. Pero en la práctica no creo que el código rápido provenga principalmente de las cosas que se hacen en el diseño del lenguaje. Como Knuth [d] señaló hace mucho tiempo, la velocidad sólo importa en ciertos cuellos de botella críticos. Y como muchos programadores han observado desde entonces, uno esta muy a menudo equivocado acerca de dónde están estos cuellos de botella.
Por tanto, en la práctica, la manera de obtener código rápido es tener un perfilador muy bueno, en lugar de, por ejemplo, hacer el lenguaje con muchos caracteres. No necesitas conocer el tipo de cada argumento en cada llamada en el programa. Necesitas poder declarar los tipos de argumentos en los cuellos de botella. Y más aún, tienes que ser capaz de descubrir dónde están los cuellos de botella.
Una queja que la gente ha tenido con Lisp es que es difícil saber qué es costoso. Esto podría ser cierto. También podría ser inevitable, si quieres tener un lenguaje muy abstracto. Y en cualquier caso, creo que un buen perfilado avanzaría mucho en la solución del problema: pronto aprenderías qué fue costoso.
Parte del problema aquí es social. A los diseñadores del lenguaje les gusta escribir compiladores rápidos. Así es como miden su habilidad. En el mejor de los casos piensan en el perfilador como un agregado. Pero en la práctica un buen perfilador puede hacer más para mejorar la velocidad de programas concretos escritos en el lenguaje que un compilador que genera código rápido. Aquí, de nuevo, los diseñadores del lenguaje están un poco fuera de contacto con sus usuarios. Hacen un trabajo realmente bueno resolviendo el problema incorrecto.
Sería una buena idea tener un perfilador activo: para enviar los datos de rendimiento al programador en lugar de esperar a que él los solicite. Por ejemplo, el editor podría mostrar los cuellos de botella en rojo cuando el programador edita el código fuente. Otro enfoque sería representar de alguna manera lo que está pasando en los programas en ejecución. Esta sería una ganancia importante especialmente en aplicaciones basadas en servidor, donde tienes que mirar un montón de programas en ejecución. Un perfilador activo podría mostrar gráficamente lo que está sucediendo en la memoria mientras se ejecuta un programa, o incluso hacer sonidos que indican lo que está sucediendo.
El sonido es una buena señal de los problemas. En un lugar en el que trabajaba teníamos un gran tablero de manecillas que mostraban lo que estaba sucediendo a nuestros servidores web. Las manecillas se movían por pequeños servomotores que hacían un ligero ruido cuando daban vuelta. No podía ver el tablero desde mi escritorio, pero descubrí que podía saber de inmediato, por el sonido, cuando había un problema con un servidor.
Incluso podría ser posible escribir un perfilador que detecta automáticamente los algoritmos ineficientes. No me sorprendería que ciertos patrones de acceso a la memoria resultaran ser signos seguros de malos algoritmos. Si hubiera un pequeño individuo corriendo por el interior de la computadora que ejecuta nuestros programas, probablemente tendría una larga y lastimera historia que contar acerca de su trabajo, al igual que un empleado de gobierno. A menudo tengo la sensación de que envío al procesador a cazar a ciegas, pero nunca he tenido una buena manera de ver lo que está haciendo.
Una cantidad de dialectos Lisp compilan ahora en código de bytes, que es luego ejecutado por un intérprete. Esto se hace normalmente para que la implementación sea más fácil de portar, pero podría ser una característica útil del lenguaje. Sería una buena idea hacer que el código de bytes sea parte oficial del lenguaje, y permitir a los programadores utilizar el código byte en línea en los cuellos de botella. Así, también tales optimizaciones serían portátiles.
La naturaleza de la velocidad, percibida por el usuario final, puede estar cambiando. Con el auge de aplicaciones basadas en servidor, más y más programas pueden resultar ser E/S. Vale la pena hacer la E/S rápida. El lenguaje puede ayudar con medidas directas como funciones de salida formateadas sencillas, rápidas, y también con profundos cambios estructurales, como almacenamiento en caché y objetos persistentes.
Los usuarios están interesados en el tiempo de respuesta. Sin embargo, otra clase de eficiencia será cada vez más importante: el número de usuarios simultáneos que puedes soportar por cada procesador. Muchas de las aplicaciones interesantes que se escribirán en el futuro cercano estarán basadas en servidor, y el número de usuarios por servidor es la cuestión fundamental para cualquier persona que aloja tales aplicaciones. En el costo capital de una empresa que ofrece una aplicación basada en servidor, este es el divisor.
Durante años, la eficacia no ha importado mucho en la mayoría de aplicaciones de usuario final. Los desarrolladores han sido capaces de asumir que cada usuario tendría un procesador cada vez más poderoso alojado en su escritorio. Y por la Ley de Parkinson [e], el software se ha ampliado para utilizar los recursos disponibles. Esto va a cambiar con aplicaciones basadas en servidor. En ese mundo, el hardware y el software se suministrarán juntos. Para las compañías que ofrecen aplicaciones basadas en servidor, hará una gran diferencia en el resultado final el número de usuarios que pueden soportar por servidor.
En algunas aplicaciones, el procesador será el factor limitante, y la velocidad de ejecución será lo más importante a optimizar. Pero a menudo la memoria será el límite; el número de usuarios simultáneos será determinado por la cantidad de memoria que necesitas para los datos de cada usuario. También aquí el lenguaje puede servir de ayuda. Un buen soporte para los hilos de ejecución (threads) le permitirá a todos los usuarios compartir un solo monticulo (heap). También puede ayudar tener objetos persistentes y/o soporte de nivel de lenguaje para carga diferida.
9 Tiempo
El último ingrediente que necesita un lenguaje popular es tiempo. A nadie le gusta escribir programas en un lenguaje que podría desaparecer, como ha sucedido con muchos lenguajes de programación. Así que la mayoría de los hackers tienden a esperar hasta que un lenguaje ha permanecido alrededor de un par de años antes de siquiera considerar usarlo.
Los inventores de maravillosas cosas nuevas se sorprenden al descubrir esto, pero necesitas tiempo para hacer llegar cualquier mensaje a la gente. Un amigo mío rara vez hace algo la primera vez que alguien se lo pide. Sabe que la gente a veces pide cosas que luego no querrán. Para evitar desperdiciar su tiempo, espera hasta la tercera o cuarta vez que se le ha pedido hacer algo; para entonces, quien se lo está pidiéndo puede estar bastante molesto, pero al menos es probable que realmente quiere lo que esta pidiendo.
La mayoría de la gente ha aprendido a hacer un tipo de filtrado similar acerca de las cosas nuevas de las que escucha hablar. Ni siquiera empiezan a prestar atención hasta que han oído hablar de algo diez veces. Están perfectamente justificados: la mayoría de las novedades resultan ser una pérdida de tiempo, y eventualmente desaparecen. Al posponer el aprendizaje de VRML [f], evité tener que aprenderlo siquiera.
Por lo tanto, cualquier persona que invente algo nuevo tiene que esperar repetir su mensaje durante años antes de que la gente empiece a entenderlo. Nosotros escribimos lo que fue, hasta donde sé, la primera aplicación basada en servidor, y nos tomó años hacer entender a las personas que no tenían que descargarla. No era que fueran estúpidos. Simplemente estábamos fuera de su frecuencia.
La buena noticia es, que la simple repetición resuelve el problema. Todo lo que tienes que hacer es seguir contando tu historia, y, finalmente, la gente comenzará a escuchar. No es cuando la gente nota que estás ahí que presta atención; es cuando se dan cuenta de que todavía sigues ahí.
Tanto es así, que por lo general toma tiempo ganar impulso. La mayoría de las tecnologías evolucionan mucho, incluso después de haber sido lanzadas por vez primera: en especial los lenguajes de programación. Nada sería mejor, para una nueva tecnología, que unos pocos años de ser utilizada sólo por un pequeño número de usuarios tempranos. Los usuarios tempranos son sofisticados y exigentes, y eliminan rápidamente cualquier falla que esté presente en tu tecnología. Cuando sólo tienes unos pocos usuarios puedes estar en estrecho contacto con todos ellos. Y los usuarios tempranos son benévolos cuando mejoras el sistema, incluso si esto les causa algún problema.
Hay dos formas en que se presenta la nueva tecnología: el método de crecimiento orgánico, y el método del Big Bang. El método de crecimiento orgánico se ejemplifica por la clásica startup [g] de garaje improvisada que arranca con fondos insuficientes. Un par de chicos que trabajan en el anonimato, desarrollan una nueva tecnología. La lanzan sin comercialización y en principio tienen sólo unos pocos (fanáticamente devotos) usuarios. Continúan mejorando la tecnología, y mientras tanto su base de usuarios crece de boca en boca. Antes de darse cuenta, son grandes.
El otro enfoque, el método del Big Bang, se ejemplifica por la fuertemente comercializada startup apoyada por capitalistas de riesgo. Se apresuran a desarrollar un producto, lo lanzan con una gran publicidad, y de inmediato (esperan) tienen una gran base de usuarios.
Por lo general, los chicos de garaje envidian a los chicos Big Bang. Los chicos Big Bang son tranquilos, seguros y respetados por los capitalistas de riesgo. Pueden darse el lujo de lo mejor de todo, y la campaña de relaciones públicas en torno al lanzamiento tiene el efecto secundario de convertirlos en celebridades. Los chicos de crecimiento orgánico, sentados en su garaje, se sienten pobres y sin amor. Y sin embargo, creo que a menudo se confunden al sentir lástima de sí mismos. El crecimiento orgánico parece dar una mejor tecnología y fundadores más ricos que el método Big Bang. Si nos fijamos en las tecnologías dominantes hoy en día, encontrarás que la mayoría de ellas creció orgánicamente.
Este patrón no sólo se aplica a las empresas. También se ve en la investigación patrocinada. Multics y Common Lisp fueron proyectos Big Bang y Unix y MacLisp eran proyectos de crecimiento orgánico.
Los inventores de maravillosas cosas nuevas se sorprenden al descubrir esto, pero necesitas tiempo para hacer llegar cualquier mensaje a la gente. Un amigo mío rara vez hace algo la primera vez que alguien se lo pide. Sabe que la gente a veces pide cosas que luego no querrán. Para evitar desperdiciar su tiempo, espera hasta la tercera o cuarta vez que se le ha pedido hacer algo; para entonces, quien se lo está pidiéndo puede estar bastante molesto, pero al menos es probable que realmente quiere lo que esta pidiendo.
La mayoría de la gente ha aprendido a hacer un tipo de filtrado similar acerca de las cosas nuevas de las que escucha hablar. Ni siquiera empiezan a prestar atención hasta que han oído hablar de algo diez veces. Están perfectamente justificados: la mayoría de las novedades resultan ser una pérdida de tiempo, y eventualmente desaparecen. Al posponer el aprendizaje de VRML [f], evité tener que aprenderlo siquiera.
Por lo tanto, cualquier persona que invente algo nuevo tiene que esperar repetir su mensaje durante años antes de que la gente empiece a entenderlo. Nosotros escribimos lo que fue, hasta donde sé, la primera aplicación basada en servidor, y nos tomó años hacer entender a las personas que no tenían que descargarla. No era que fueran estúpidos. Simplemente estábamos fuera de su frecuencia.
La buena noticia es, que la simple repetición resuelve el problema. Todo lo que tienes que hacer es seguir contando tu historia, y, finalmente, la gente comenzará a escuchar. No es cuando la gente nota que estás ahí que presta atención; es cuando se dan cuenta de que todavía sigues ahí.
Tanto es así, que por lo general toma tiempo ganar impulso. La mayoría de las tecnologías evolucionan mucho, incluso después de haber sido lanzadas por vez primera: en especial los lenguajes de programación. Nada sería mejor, para una nueva tecnología, que unos pocos años de ser utilizada sólo por un pequeño número de usuarios tempranos. Los usuarios tempranos son sofisticados y exigentes, y eliminan rápidamente cualquier falla que esté presente en tu tecnología. Cuando sólo tienes unos pocos usuarios puedes estar en estrecho contacto con todos ellos. Y los usuarios tempranos son benévolos cuando mejoras el sistema, incluso si esto les causa algún problema.
Hay dos formas en que se presenta la nueva tecnología: el método de crecimiento orgánico, y el método del Big Bang. El método de crecimiento orgánico se ejemplifica por la clásica startup [g] de garaje improvisada que arranca con fondos insuficientes. Un par de chicos que trabajan en el anonimato, desarrollan una nueva tecnología. La lanzan sin comercialización y en principio tienen sólo unos pocos (fanáticamente devotos) usuarios. Continúan mejorando la tecnología, y mientras tanto su base de usuarios crece de boca en boca. Antes de darse cuenta, son grandes.
El otro enfoque, el método del Big Bang, se ejemplifica por la fuertemente comercializada startup apoyada por capitalistas de riesgo. Se apresuran a desarrollar un producto, lo lanzan con una gran publicidad, y de inmediato (esperan) tienen una gran base de usuarios.
Por lo general, los chicos de garaje envidian a los chicos Big Bang. Los chicos Big Bang son tranquilos, seguros y respetados por los capitalistas de riesgo. Pueden darse el lujo de lo mejor de todo, y la campaña de relaciones públicas en torno al lanzamiento tiene el efecto secundario de convertirlos en celebridades. Los chicos de crecimiento orgánico, sentados en su garaje, se sienten pobres y sin amor. Y sin embargo, creo que a menudo se confunden al sentir lástima de sí mismos. El crecimiento orgánico parece dar una mejor tecnología y fundadores más ricos que el método Big Bang. Si nos fijamos en las tecnologías dominantes hoy en día, encontrarás que la mayoría de ellas creció orgánicamente.
Este patrón no sólo se aplica a las empresas. También se ve en la investigación patrocinada. Multics y Common Lisp fueron proyectos Big Bang y Unix y MacLisp eran proyectos de crecimiento orgánico.
10 Rediseño
E.B. White escribió: "La mejor escritura es la reescritura". Todo buen escritor lo sabe, y también es cierto para el software. La parte más importante del diseño es rediseñar. Los lenguajes de programación, en especial, no se rediseñan lo suficiente.
Para escribir buen software debes mantener dos ideas opuestas en la cabeza simultáneamente. Necesitas la fe ingenua del joven hacker en sus habilidades y, al mismo tiempo, el escepticismo de los veteranos. Tienes que ser capaz de pensar, con una mitad del cerebro: ¿que tan difícil puede ser?, mientras que con la otra piensas: nunca va a funcionar.
El truco es darse cuenta de que no hay una verdadera contradicción aquí. Quieres ser optimista y escéptico acerca de dos cosas diferentes. Tienes que ser optimista acerca de la posibilidad de resolver el problema, pero escéptico sobre el valor de cualquier solución que hasta el momento hayas conseguido.
Las personas que hacen buenos trabajos a menudo piensan que en lo que están trabajando no es bueno. Otros ven lo que han hecho y están llenos de asombro, pero el creador está lleno de preocupación. Este patrón no es casual: es la preocupación la que hizo bueno el trabajo.
Si puedes mantener equilibradas la esperanza y la preocupación, impulsarán hacia adelante un proyecto de la misma forma en que tus piernas impulsan hacia adelante una bicicleta. En la primera fase del motor de dos ciclos de la innovación, trabajas furiosamente en algún problema, inspirado por tu confianza en que serás capaz de resolverlo. En la segunda fase, contemplas lo que has hecho a la fría luz de la mañana, y ves todos sus defectos con mucha claridad. Pero siempre y cuando tu espíritu crítico no supere tu esperanza, serás capaz de mirar tu ciertamente incompleto sistema, y pensar, ¿qué tan difícil puede ser conseguir lo que falta?, continuando así el ciclo.
Es difícil mantener las dos fuerzas en equilibrio. En los hackers jóvenes predomina el optimismo. Producen algo, están convencidos de que es genial, y nunca lo mejoran. En los hackers de edad predomina el escepticismo, y ni siquiera se atreverán a embarcarse en proyectos ambiciosos.
Cualquier cosa que puedas hacer para mantener el ciclo de rediseño es bueno. La prosa puede ser reescrita una y otra vez hasta que estés satisfecho con ella. Pero el software, por regla general, no se rediseña lo suficiente. La prosa tiene lectores, pero el software tiene usuarios. Si un escritor reescribe un ensayo, es poco probable que las personas que leyeron la versión anterior se quejen de que sus pensamientos se han roto por algún tipo de incompatibilidad de reciente introducción.
Los usuarios son un arma de doble filo. Pueden ayudarte a mejorar tu lenguaje, pero también pueden disuadirte de hacerlo. Así que elige a tus usuarios con cuidado, y sé lento para hacer crecer su número. Tener usuarios es como la optimización: lo sabio es demorarla. También, como regla general, en cualquier momento puedes salirte con la tuya cambiando más de lo que piensas. Introducir cambios es como retirar un vendaje: el dolor es un recuerdo casi tan pronto como lo sientes.
Todo el mundo sabe que no es buena idea tener un lenguaje diseñado por comité. Los comités arrojan malos diseños. Pero creo que el peor peligro de los comités es que interfieren con el rediseño. Es tanto trabajo introducir cambios que nadie quiere molestarse en hacerlo. Cualquier cosa que el comité decida tiende a permanecer de esa manera, incluso si a la mayoría de los miembros no les gusta.
Incluso un comité de dos se interpone en el camino del rediseño. Esto ocurre especialmente en las interfaces, entre piezas de software escritas por dos personas diferentes. Para cambiar la interfaz ambos tienen que estar de acuerdo en cambiarla a la vez. Y por lo tanto, tienden a no cambiarla en absoluto, lo cual es un problema, porque tiende a ser una de las partes más ad hoc de cualquier sistema.
Una solución a este problema sería diseñar sistemas para que las interfaces sean horizontales en vez de verticales― para que los módulos sean siempre estratos de abstracción apilados verticalmente. Entonces, la interfaz tendería a ser propiedad de uno de ellos. El menor de los dos niveles tendrá que ser un lenguaje en el que se escribe la parte superior, en cuyo caso el nivel más bajo será el propietario de la interfaz, o será un esclavo, en cuyo caso la interfaz puede ser dictada por el nivel superior.
Para escribir buen software debes mantener dos ideas opuestas en la cabeza simultáneamente. Necesitas la fe ingenua del joven hacker en sus habilidades y, al mismo tiempo, el escepticismo de los veteranos. Tienes que ser capaz de pensar, con una mitad del cerebro: ¿que tan difícil puede ser?, mientras que con la otra piensas: nunca va a funcionar.
El truco es darse cuenta de que no hay una verdadera contradicción aquí. Quieres ser optimista y escéptico acerca de dos cosas diferentes. Tienes que ser optimista acerca de la posibilidad de resolver el problema, pero escéptico sobre el valor de cualquier solución que hasta el momento hayas conseguido.
Las personas que hacen buenos trabajos a menudo piensan que en lo que están trabajando no es bueno. Otros ven lo que han hecho y están llenos de asombro, pero el creador está lleno de preocupación. Este patrón no es casual: es la preocupación la que hizo bueno el trabajo.
Si puedes mantener equilibradas la esperanza y la preocupación, impulsarán hacia adelante un proyecto de la misma forma en que tus piernas impulsan hacia adelante una bicicleta. En la primera fase del motor de dos ciclos de la innovación, trabajas furiosamente en algún problema, inspirado por tu confianza en que serás capaz de resolverlo. En la segunda fase, contemplas lo que has hecho a la fría luz de la mañana, y ves todos sus defectos con mucha claridad. Pero siempre y cuando tu espíritu crítico no supere tu esperanza, serás capaz de mirar tu ciertamente incompleto sistema, y pensar, ¿qué tan difícil puede ser conseguir lo que falta?, continuando así el ciclo.
Es difícil mantener las dos fuerzas en equilibrio. En los hackers jóvenes predomina el optimismo. Producen algo, están convencidos de que es genial, y nunca lo mejoran. En los hackers de edad predomina el escepticismo, y ni siquiera se atreverán a embarcarse en proyectos ambiciosos.
Cualquier cosa que puedas hacer para mantener el ciclo de rediseño es bueno. La prosa puede ser reescrita una y otra vez hasta que estés satisfecho con ella. Pero el software, por regla general, no se rediseña lo suficiente. La prosa tiene lectores, pero el software tiene usuarios. Si un escritor reescribe un ensayo, es poco probable que las personas que leyeron la versión anterior se quejen de que sus pensamientos se han roto por algún tipo de incompatibilidad de reciente introducción.
Los usuarios son un arma de doble filo. Pueden ayudarte a mejorar tu lenguaje, pero también pueden disuadirte de hacerlo. Así que elige a tus usuarios con cuidado, y sé lento para hacer crecer su número. Tener usuarios es como la optimización: lo sabio es demorarla. También, como regla general, en cualquier momento puedes salirte con la tuya cambiando más de lo que piensas. Introducir cambios es como retirar un vendaje: el dolor es un recuerdo casi tan pronto como lo sientes.
Todo el mundo sabe que no es buena idea tener un lenguaje diseñado por comité. Los comités arrojan malos diseños. Pero creo que el peor peligro de los comités es que interfieren con el rediseño. Es tanto trabajo introducir cambios que nadie quiere molestarse en hacerlo. Cualquier cosa que el comité decida tiende a permanecer de esa manera, incluso si a la mayoría de los miembros no les gusta.
Incluso un comité de dos se interpone en el camino del rediseño. Esto ocurre especialmente en las interfaces, entre piezas de software escritas por dos personas diferentes. Para cambiar la interfaz ambos tienen que estar de acuerdo en cambiarla a la vez. Y por lo tanto, tienden a no cambiarla en absoluto, lo cual es un problema, porque tiende a ser una de las partes más ad hoc de cualquier sistema.
Una solución a este problema sería diseñar sistemas para que las interfaces sean horizontales en vez de verticales― para que los módulos sean siempre estratos de abstracción apilados verticalmente. Entonces, la interfaz tendería a ser propiedad de uno de ellos. El menor de los dos niveles tendrá que ser un lenguaje en el que se escribe la parte superior, en cuyo caso el nivel más bajo será el propietario de la interfaz, o será un esclavo, en cuyo caso la interfaz puede ser dictada por el nivel superior.
11 Lisp
Lo que todo esto implica es que hay esperanza para un nuevo Lisp. Hay esperanza para cualquier lenguaje que les dé a los hackers lo que quieren, incluyendo a Lisp. Creo que pudimos haber cometido un error al pensar que los hackers no se emocionan ante Lisp por su extrañeza. Esta reconfortante ilusión pudo habernos impedido ver el verdadero problema con Lisp, o por lo menos con Common Lisp: que es malo para hacer lo que los hackers quieren hacer. El lenguaje de un hacker necesita bibliotecas potentes y algo para hackear. Common Lisp no tiene ninguna de las dos. El lenguaje de un hacker es conciso y hackeable. Common Lisp no lo es.
La buena noticia es: Lisp no apesta, sino Common Lisp. Creo que si somos capaces de desarrollar un nuevo Lisp que sea un verdadero lenguaje de hacker, estos lo utilizaran. Utilizaran cualquier lenguaje que haga el trabajo. Todo lo que tenemos que hacer es asegurarnos de que este nuevo Lisp haga algunos trabajos importantes mejor que otros lenguajes.
La historia nos ofrece algo de motivación. Con el tiempo, los sucesivos lenguajes de programación nuevos han tomado más y más características de Lisp. Ya no hay mucho por copiar antes de que el lenguaje que hagas sea Lisp. El ultimo lenguaje de moda, Python, es una versión diluida de Lisp con sintaxis infijay sin macros. Un Lisp nuevo sería un paso natural en esta progresión.
A veces pienso que sería un buen truco de marketing llamarla una versión mejorada de Python. Eso suena más moderno que Lisp. Para muchas personas, Lisp es un lento lenguaje de Inteligencia Artificial con una gran cantidad de paréntesis. La biografía oficial de Fritz Kunze evita cuidadosamente mencionar la palabra Lisp. Pero yo creo que no debemos tener miedo de llamar al nuevo Lisp Lisp. Lisp todavía tiene mucho respeto latente entre los mejores hackers― por ejemplo, los que tomaron 6.001 [h] y la comprendieron. Y esos son los usuarios que necesitas para ganar.
En "Cómo Convertirse en Hacker", Eric Raymond describe a Lisp como algo parecido al latín o al griego: un lenguaje que debes aprender a manera de ejercicio intelectual, a pesar de que en realidad no lo vayas a usar:
Vale la pena aprender Lisp por la profunda experiencia de iluminación que obtendrás cuando finalmente lo entiendas; esa experiencia te hará un mejor programador el resto de tus días, incluso si en realidad nunca utilizas Lisp mucho.
Si no conociera Lisp, leer esto haria que me pusiera a hacer preguntas. Un lenguaje que me convertirá en un mejor programador, si significa algo, significa un lenguaje que sería mejor para la programación. Y esa es, de hecho, la implicación de lo que dice Eric.
Creo que mientras la idea todavía este flotando por ahí, los hackers estarán suficientemente receptivos para un nuevo Lisp, aunque se llame Lisp. Pero este Lisp debe ser un lenguaje de hacker, como los Lisps clásicos de la década de 1970. Debe ser conciso, sencillo y hackeable. Y debe tener bibliotecas potentes para hacer lo que los hackers quieren hacer ahora.
En materia de bibliotecas creo que hay espacio para vencer a lenguajes como Perl y Python en su propio juego. Muchas de las nuevas aplicaciones que necesitaran ser escritas en los próximos años serán aplicaciones basadas en servidor. No hay razón para que un nuevo Lisp no tenga bibliotecas de cadenas tan buenas como Perl, y si este nuevo Lisp tiene también bibliotecas potentes para aplicaciones basadas en servidor, será muy popular. Los auténticos hackers no darían la espalda a una nueva herramienta que les permita resolver problemas difíciles con unas pocas llamadas a biblioteca. Recuerda, los hackers son perezosos.
Sería un acierto aún mayor tener soporte de lenguaje del nucleo para aplicaciones basadas en servidor. Por ejemplo, apoyo explícito para programas con múltiples usuarios, o propiedad de los datos a nivel de las etiquetas de tipo.
Las aplicaciones basadas en servidor también nos dan la respuesta a la pregunta de qué se habrá de hackear con este nuevo Lisp. No estaría de más mejorar a Lisp como lenguaje de escritura de Unix. (Sería difícil hacerlo peor.) Pero creo que hay áreas donde los lenguajes actuales serían más fáciles de superar. Creo que sería mejor seguir el modelo de Tcl, y suministrar el Lisp junto con un sistema completo para el apoyo a aplicaciones basadas en servidor. Lisp es un paso natural para aplicaciones basadas en servidor. Las clausuras léxicas proporcionan una manera de conseguir el efecto de las subrutinas cuando la interfaz de usuario es sólo una serie de páginas web. Las expresiones S se ajustan muy bien en html, y las macros son buenas generandolas. Necesita haber mejores herramientas para la escritura de aplicaciones basadas en servidor, y es necesario que haya un nuevo Lisp, y los dos trabajarían muy bien juntos.
Creo que mientras la idea todavía este flotando por ahí, los hackers estarán suficientemente receptivos para un nuevo Lisp, aunque se llame Lisp. Pero este Lisp debe ser un lenguaje de hacker, como los Lisps clásicos de la década de 1970. Debe ser conciso, sencillo y hackeable. Y debe tener bibliotecas potentes para hacer lo que los hackers quieren hacer ahora.
En materia de bibliotecas creo que hay espacio para vencer a lenguajes como Perl y Python en su propio juego. Muchas de las nuevas aplicaciones que necesitaran ser escritas en los próximos años serán aplicaciones basadas en servidor. No hay razón para que un nuevo Lisp no tenga bibliotecas de cadenas tan buenas como Perl, y si este nuevo Lisp tiene también bibliotecas potentes para aplicaciones basadas en servidor, será muy popular. Los auténticos hackers no darían la espalda a una nueva herramienta que les permita resolver problemas difíciles con unas pocas llamadas a biblioteca. Recuerda, los hackers son perezosos.
Sería un acierto aún mayor tener soporte de lenguaje del nucleo para aplicaciones basadas en servidor. Por ejemplo, apoyo explícito para programas con múltiples usuarios, o propiedad de los datos a nivel de las etiquetas de tipo.
Las aplicaciones basadas en servidor también nos dan la respuesta a la pregunta de qué se habrá de hackear con este nuevo Lisp. No estaría de más mejorar a Lisp como lenguaje de escritura de Unix. (Sería difícil hacerlo peor.) Pero creo que hay áreas donde los lenguajes actuales serían más fáciles de superar. Creo que sería mejor seguir el modelo de Tcl, y suministrar el Lisp junto con un sistema completo para el apoyo a aplicaciones basadas en servidor. Lisp es un paso natural para aplicaciones basadas en servidor. Las clausuras léxicas proporcionan una manera de conseguir el efecto de las subrutinas cuando la interfaz de usuario es sólo una serie de páginas web. Las expresiones S se ajustan muy bien en html, y las macros son buenas generandolas. Necesita haber mejores herramientas para la escritura de aplicaciones basadas en servidor, y es necesario que haya un nuevo Lisp, y los dos trabajarían muy bien juntos.
12 El Lenguaje Soñado
A manera de sumario, tratemos de describir el lenguaje soñado de un hacker. El lenguaje soñado es bello, limpio y conciso. Tiene un nivel superior interactivo que arranca rápido. Puedes escribir programas para resolver problemas comunes con muy poco código. Casi todo el código en cualquier programa que escribes es código especifico a tu aplicación. Todo lo demás ha sido hecho para ti.
La sintaxis del lenguaje es breve al extremo. Nunca tienes que teclear un carácter innecesario o incluso utilizar mucho la tecla de mayúsculas.
Utilizando abstracciones grandes puedes escribir muy rápido la primera versión de un programa. Más tarde, cuando desees optimizar, hay un perfilador muy bueno, que te dice dónde enfocar tu atención. Puedes hacer bucles internos sorprendentemente rápido, incluso escribir código de bytes en línea si es necesario.
Hay muchos buenos ejemplos para aprender, y el lenguaje es lo suficientemente intuitivo que puedes aprender a utilizarlo a partir de ejemplos en un par de minutos. No necesitas buscar mucho en el manual. El manual es delgado, y tiene algunas advertencias y requisitos.
El lenguaje tiene un núcleo pequeño, y bibliotecas potentes, altamente ortogonales, las cuales están tan cuidadosamente diseñadas como el núcleo del lenguaje. Todas las bibliotecas trabajan bien juntas; todo en el lenguaje encaja como las piezas en una buena cámara. Nada ha quedado en desuso o ha sido mantenido por compatibilidad. El código fuente de todas las bibliotecas esta disponible fácilmente. Es fácil hablar con el sistema operativo y las aplicaciones escritas en otros lenguajes.
El lenguaje esta construido por capas. Las abstracciones de alto nivel están construidas de una manera muy transparente a partir de abstracciones de bajo nivel, que se pueden conseguir si lo deseas.
Nada está escondido de ti que no sea absolutamente necesario que lo esté. El lenguaje ofrece abstracciones sólo como una forma de ahorrarte trabajo, más que como una manera de decirte qué hacer. De hecho, el lenguaje te alienta a ser un mismo participante en su diseño. Puedes cambiar todo de él, incluyendo su sintaxis, y todo lo que escribas tiene, tanto como sea posible, el mismo estatus como lo que viene predefinido.
Notas
[1] Las macros más cercanas a la idea moderna fueron propuestas por Timothy Hart en 1964, dos años después de que Lisp 1.5 fuera lanzado. Lo que faltaba, en un principio, eran formas de evitar la captura variable y la evaluación múltiple; los ejemplos de Hart están sujetos a ambos.
[2] En Cuando el Aire Golpea tu Cerebro, el neurocirujano Frank Vertosick relata una conversación en la que su jefe de residentes, Gary, habla sobre la diferencia entre cirujanos e internistas ("pulgas"):
Gary y yo pedimos una pizza grande y encontramos una cabina abierta. El jefe encendió un cigarrillo. "Mira a esas malditas pulgas, charlando sobre algunas enfermedades que sólo veran una vez en su vida. Ése es el problema con las pulgas, sólo les gustan las cosas extrañas. Odian los casos ordinarios. Esa es la diferencia entre nosotros y las malditas pulgas. Veras, a nosotros nos encantan las grandes y jugosas hernias de disco lumbar, pero ellos odian la hipertensión..."
Es difícil pensar en una hernia de disco lumbar como jugosa (excepto literalmente). Y sin embargo, creo que sé lo que quieren decir. A menudo he tenido que localizar un bug jugoso. A alguien que no sea programador le resultara difícil imaginar que podría haber placer en un bug. Sin duda, es mejor si todo funciona. En cierto modo, lo es. Y sin embargo, hay sin duda una sombría satisfacción en cazar cierta clase de bugs.Notas del Traductor
[a] En La Palabra Hacker Paul Graham da la siguiente descripción: “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] Massachusetts Institute of Technology.
[c] Common Lisp the Lenguaje (Common Lisp el Lenguaje) es un influyente libro de Guy L. Steele acerca de Common Lisp. La primera edición aparecio en 1984 y sirvio como la base para el estándar ANSI Common Lisp. [Fuente: Wikipedia en Inglés. Ver.]
[d] 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.]
[e] La Ley de Parkinson afirma que "el trabajo se expande hasta llenar el tiempo disponible para que se termine". Para muchos, cuando más tiempo se tenga para hacer algo, más divagará la mente y más problemas serán planteados.
"Ley de Parkinson" también se usa para referirse a un derivado del original relacionado con computadoras: "Los datos se expanden hasta llenar el espacio disponible para el almacenamiento"; comprar más memoria incentiva el uso de técnicas de programación que usan la memoria de forma más intensiva. Se ha observado en los últimos 10 años que el uso de memoria de los sistemas ha mostrado una tendencia a duplicarse aproximadamente una vez cada 18 meses. Afortunadamente, la densidad de memoria disponible por un dinero constante también tiende a duplicarse cada 12 meses (ver Ley de Moore). Desafortunadamente, las leyes de la física garantizan que esto no puede seguir indefinidamente. [Fuente: Wikipedia. Ver.]
[f] VRML (sigla del inglés Virtual Reality Modeling Language. "Lenguaje para Modelado de Realidad Virtual"). Formato de archivo normalizado que tiene como objetivo la representación de escenas u objetos interactivos tridimensionales; diseñado particularmente para su empleo en la web.
[g] El termino startup define a una empresa de reciente creación orientada a la tecnología. El mismo Paul Graham la define a la perfección en Como Financiar una Startup: "Una empresa tiene que ser más que pequeña y de reciente creación para ser una startup. Hay millones de pequeñas empresas en Estados Unidos, pero sólo unas pocas miles son startups. Para ser una startup, una compañía tiene que ser un negocio de productos, no un negocio de servicios. Lo que no quiere decir que tiene que hacer algo físico, sino que tiene que tener una cosa que vende a mucha gente, en vez de hacer trabajos a medida para clientes individuales. El trabajo sobre encargo no es escalable. Para ser una startup tienes que ser la banda que vende un millón de copias de una canción, no el grupo que gana dinero tocando en bodas y Bar Mitzvahs individuales."
[h] Structure and Interpretation of Computer Programs (SICP) (Estructura e Interpretación de Programas Computacionales) es un libro de texto publicado en 1984 sobre conceptos generales de programación computacional de MIT Press escrito por los profesores Harold Abelson y Gerald Jay Sussman, junto con Julie Sussman del Massachusetts Institute of Technology (MIT). Fue utilizado como libro de texto de introducción a la programación en las clases del MIT y otras escuelas.
Utilizando un dialecto del lenguaje de programación Lisp llamado Scheme, el libro explica los conceptos fundamentales de la informática, incluyendo la abstracción, la recursividad, los intérpretes y la abstracción metalingüística, y enseña la programación modular.
Fue usado como libro de texto del antiguo curso introductorio a la clase de programación 6.001 en el MIT. [Fuente: Wikipedia en Inglés. Ver.]