Filosofía de la ingeniería: Roberto Ierusalimschy

Ideas clave
- Diseñó el lenguaje de scripting que se esconde dentro de una enorme porción del software que usas. Roberto Ierusalimschy lideró el diseño de Lua, creado en 1993 en el laboratorio Tecgraf de la PUC-Rio junto a Luiz Henrique de Figueiredo y Waldemar Celes. Hace funcionar la lógica de juego de World of Warcraft, Roblox (mediante su dialecto Luau), Dota 2 y Garry’s Mod, programa Redis y nginx (a través de OpenResty), impulsa Adobe Lightroom y Wireshark, y se incrusta en dispositivos que llegan hasta robots sin ningún sistema operativo por debajo.127
- Mecanismos, no políticas. La decisión que define a Lua es una negativa: no incluye un sistema de clases, ni un modelo de objetos, ni un paradigma. Te ofrece unos pocos mecanismos potentes y generales (tablas, metatablas, corrutinas) y te deja construir tus propias abstracciones encima. “Lua no impone ningún modelo de objetos o de clases al programador”, escribieron sus diseñadores; en cambio, “proporcionamos mecanismos flexibles” para que puedas construir el modelo que mejor se ajuste a la aplicación.3
- La pequeñez es una función, no una limitación. La implementación de referencia es diminuta y limpia: el código fuente de Lua 5.1 ronda las 17.000 líneas de C, la distribución completa cabe en un disquete y el intérprete compilado pesa aproximadamente 143 KB. La mayoría de los lenguajes de scripting son un orden de magnitud más grandes; Lua se mantiene pequeño precisamente porque está pensado para incrustarse, y la simplicidad es lo que hace posible una implementación pequeña y rápida.3
- La portabilidad y la facilidad de incrustación fueron objetivos de diseño desde el primer día. Lua está escrito en “C limpio” —la intersección entre C y C++— y “compila sin más en la mayoría de las plataformas”, desde Linux y Windows hasta dispositivos de mano y microcontroladores. Una API de C bien definida permite que un programa anfitrión lo controle y lo amplíe por completo, que es exactamente la razón por la que la industria de los videojuegos lo adoptó casi como un estándar.34
El principio
“No quisimos convertir Lua en un lenguaje orientado a objetos porque no queríamos fijar un paradigma de programación para Lua… Lua no impone ningún modelo de objetos o de clases al programador. En cambio… decidimos proporcionar mecanismos flexibles que permitieran al programador construir el modelo que resultara adecuado para la aplicación.” – Roberto Ierusalimschy, Luiz Henrique de Figueiredo y Waldemar Celes, The Evolution of Lua3
Buena parte del diseño de lenguajes es la acumulación de políticas. Un equipo decide que los objetos deben funcionar de esta manera, que el manejo de errores debe verse de aquella otra, que la concurrencia significa hilos, o asincronía, o actores —y hornean esas decisiones dentro del lenguaje, de modo que todo programa escrito en él hereda las elecciones. Las decisiones suelen ser razonables. El problema es que son decisiones, tomadas una vez, para todo el mundo, por gente que no podía conocer tu aplicación. El instinto de Ierusalimschy corría en la dirección contraria. En lugar de decidir por ti, Lua te entrega un pequeño conjunto de mecanismos generales y se aparta del camino, para que puedas construir la política que tu problema realmente necesita.3
El caso más claro es la orientación a objetos. A comienzos de los años noventa, cuando la programación orientada a objetos estaba en la cima de su moda, los usuarios presionaron al equipo de Lua para que añadiera clases y herencia. Se negaron —no porque la OOP fuera errónea, sino porque fijar un solo modelo era erróneo para un lenguaje pensado para incrustarse en aplicaciones tremendamente distintas. Los objetos y las clases “podían implementarse con tablas si hacía falta”, razonaron, ya que una tabla puede contener tanto datos como métodos y las funciones son valores de primera clase.3 Así que, en vez de un sistema de objetos, construyeron una semántica extensible —un mecanismo que te permite intervenir en cómo se comportan las tablas— y dejaron que los usuarios ensamblaran por sí mismos la herencia, los valores por defecto, las vistas de solo lectura y jerarquías de clases completas. “La semántica extensible se ha convertido en un sello distintivo de Lua”, escribieron, y “no hemos cambiado de opinión hasta el día de hoy”.3
Esa negativa solo resulta asequible gracias a otros tres compromisos que la acompañan. La simplicidad: el lenguaje se mantiene lo bastante pequeño como para que los mecanismos sean comprensibles y la implementación sea correcta. La pequeñez como función: la implementación de referencia completa ronda las 17.000 líneas de C limpio, lo bastante pequeña como para que añadir Lua a una aplicación “no la infle”.3 Y la portabilidad: escribir en la intersección entre C y C++ significa que el mismo código fuente compila en todas partes, desde una supercomputadora hasta un sensor.3 Dale a la gente unas pocas palancas afiladas y generales en lugar de un armario lleno de botones ya decididos, y mantén todo el conjunto lo bastante pequeño como para llevarlo a cualquier parte. Ese es el principio, y todo lo demás en Lua es una consecuencia suya.
Contexto
Roberto Ierusalimschy nació el 21 de mayo de 1960 en Río de Janeiro, y toda su trayectoria profesional ha permanecido cerca de una sola institución: la Pontificia Universidad Católica de Río de Janeiro (PUC-Rio), donde obtuvo su doctorado en ciencias de la computación en 1990 y donde es catedrático de informática. Hizo un posdoctorado en la Universidad de Waterloo y una estancia como profesor visitante en Stanford, pero la PUC-Rio es su casa, y la historia de Lua es inseparable de un laboratorio concreto que hay allí.5
Ese laboratorio es Tecgraf, el Grupo de Tecnología en Computación Gráfica, fundado en 1987 para construir herramientas de software para clientes industriales —uno de los más grandes de los cuales era, y sigue siendo, la petrolera brasileña Petrobras.3 El origen de Lua es en parte una historia sobre la política comercial brasileña. Desde 1977 hasta 1992, Brasil mantuvo una política de fuertes barreras comerciales —una “reserva de mercado”— sobre el hardware y el software informáticos, impulsada por la convicción nacionalista de que el país podía y debía construir lo suyo propio. En ese clima, los clientes de Tecgraf “no podían permitirse, ni política ni financieramente, comprar software a medida en el extranjero”. Comprar herramientas extranjeras suponía un “complicado proceso burocrático para demostrar que sus necesidades no podían ser satisfechas por empresas brasileñas”. Aquellas restricciones, sumadas al aislamiento geográfico de Brasil respecto de otros centros de investigación, “llevaron a Tecgraf a implementar desde cero las herramientas básicas que necesitaba”.3 Lua es, según las propias palabras de sus diseñadores, “el único lenguaje creado en un país en desarrollo que ha alcanzado relevancia global”.3
Antes de Lua hubo dos pequeños lenguajes, ambos construidos para Petrobras. DEL —“data-entry language”, lenguaje de entrada de datos— generaba interfaces gráficas para que los ingenieros pudieran introducir los datos de los simuladores haciendo clic en un diagrama en lugar de editar columnas de números.3 SOL —“Simple Object Language”— era un lenguaje de configuración para un generador de informes, con una sintaxis de declaración de tipos influida por BibTeX.3 A comienzos de 1993, ambos habían desbordado su alcance original; los usuarios de DEL querían un control de flujo de verdad, y SOL necesitaba potencia procedimental. A mediados de 1993, Ierusalimschy, de Figueiredo y Celes concluyeron que los dos podían reemplazarse por un único lenguaje más potente —y así nació el equipo de Lua.3 El nombre es una pequeña broma que se quedó. SOL significa “sol” en portugués; un amigo en Tecgraf, Carlos Henrique Levy, sugirió llamar al sucesor ‘Lua’ —“luna” en portugués.3 Para julio de 1993, Waldemar Celes había terminado la primera implementación, construida como proyecto de un curso supervisado por Ierusalimschy y siguiendo el principio de la Programación Extrema de “la cosa más simple que pudiera funcionar”.3
El trabajo
Tablas y metatablas: una estructura de datos, un mecanismo
Empieza por la tabla, porque es todo el lenguaje en miniatura. Lua ofrece un único mecanismo de estructuración de datos —la tabla, su término para un arreglo asociativo— y esa sola estructura hace el trabajo de registros, arreglos, conjuntos, listas, módulos y objetos.3 “Aunque la mayoría de los lenguajes de scripting ofrecen arreglos asociativos”, señalan sus diseñadores, “en ningún otro lenguaje los arreglos asociativos desempeñan un papel tan central”.3 Un registro es una tabla indexada por nombres de campo; un arreglo es una tabla indexada por enteros; un objeto es una tabla que resulta contener a la vez datos y métodos. Un mecanismo, muchos usos —que es exactamente la apuesta de “mecanismos, no políticas” aplicada a los datos.
La palanca que hace programables a las tablas es la metatabla. Normalmente, buscar una clave que la tabla no tiene devuelve nil. Pero puedes dotar a una tabla de una metatabla —una segunda tabla que describe cómo debería comportarse la primera en situaciones inusuales. La entrada más importante es __index: cuando una búsqueda falla, Lua consulta el __index de la metatabla, que puede apuntar a otra tabla donde seguir buscando. Encadena varias y tendrás herencia construida a partir de nada más que tablas y una única redirección. El mismo mecanismo, bajo distintos metamétodos, te da sobrecarga de operadores, valores por defecto, proxies de solo lectura y campos perezosos. Nada de eso es una función del lenguaje en el sentido habitual: todo es un solo mecanismo, usado en distintas formas.3
Este mecanismo no llegó entero —su evolución es, en sí misma, una lección de contención. Comenzó en Lua 2.1 (1995) como “fallbacks”: ganchos que Lua invocaba cuando una operación se aplicaba al tipo de valor “equivocado”, de modo que el programador pudiera decidir qué ocurría a continuación.3 El fallback de indexación de tablas permitía que los userdata y otros valores “se comportaran como tablas”, soportando “muchas formas de herencia (mediante delegación)”.3 Los fallbacks eran globales —un gancho por evento—, lo que los hacía incómodos de compartir entre bibliotecas, así que Lua 3.0 (1997) los reemplazó por “tag methods” por tipo, y Lua 5.0 (2003) unificó todo en metatablas y metamétodos, la forma que Lua usa hoy. (El término “metatabla” fue sugerido por Rici Lake en 2001.)3 Cada paso generalizó el mecanismo en lugar de amontonar nuevas funciones —el mismo instinto que mantuvo al lenguaje negándose a incluir un sistema de clases.
La facilidad de incrustación, la API de C, y por qué los videojuegos adoptaron Lua
Lua no está pensado realmente para ser un lenguaje autónomo. Sus diseñadores lo llaman un “lenguaje de extensión extensible” —un lenguaje de extensión porque extiende una aplicación anfitriona mediante configuración y scripting, y extensible porque a su vez puede ampliarse con funciones de C.3 La bisagra es una API de C bien definida que “permite la comunicación plena entre el código Lua y el código externo”, construida en torno a una metáfora de pila limpia para pasar valores de ida y vuelta entre Lua y el anfitrión. La API permite que Lua se conecte no solo con C y C++ sino, a través de ellos, con Fortran, Java, C# y otros lenguajes por completo.3
La recompensa llegó en los videojuegos, y la historia es concreta. En enero de 1997, Bret Mogilefsky —programador principal de la aventura de LucasArts Grim Fandango— le contó al equipo de Lua que había reemplazado el lenguaje de scripting casero del juego por Lua, y que “una cantidad tremenda del juego estaba escrita en Lua”.3 Mogilefsky habló de ello en una mesa redonda de la Game Developers’ Conference, y a partir de ahí “Lua se difundió de boca en boca entre los desarrolladores de videojuegos hasta convertirse en una habilidad definitivamente comercializable en la industria del videojuego”.3 El encaje es estructural. Un motor de juego es exactamente el tipo de anfitrión que se beneficia de una capa de scripting incrustada —el trabajo pesado (renderizado, física) permanece en C++ rápido, mientras que la lógica de juego, las misiones y el comportamiento viven en pequeños scripts de Lua que los diseñadores pueden editar y recargar sin recompilar el motor. Pequeño, rápido, portable y fácil de incrustar era precisamente el perfil que un juego necesitaba, y Lua se había construido para eso desde su primera versión.34
Corrutinas, y una implementación pequeña y rápida
El tercer gran mecanismo es la corrutina —y, como la OOP, es una negativa deliberada del equipo a fijar una política. A lo largo de finales de los noventa, los usuarios presionaron por la multitarea con hilos, y el movimiento obvio era adoptar el modelo estándar de hilos preemptivos y memoria compartida. El equipo de Lua se negó, por dos razones: implementar hilos preemptivos en C requiere primitivas “que no forman parte de ANSI C”, lo que habría roto la portabilidad de Lua y —algo más fundamental— “no creíamos (y seguimos sin creer) en el modelo estándar de multithreading”, donde “nadie puede escribir programas correctos en un lenguaje en el que ‘a=a+1’ no es determinista”.3 Así que, en lugar de hilos, lanzaron corrutinas en Lua 5.0 (2003): un mecanismo para la multitarea cooperativa, no preemptiva, en el que una función puede suspenderse a sí misma y luego reanudarse exactamente donde lo dejó.3 Las corrutinas te dan la expresividad de la concurrencia —generadores, planificadores cooperativos, máquinas de estado— sin el indeterminismo que hace tan difícil acertar con los hilos de memoria compartida. Un mecanismo, no una política, una vez más.
Por debajo de todo ello hay una implementación que es rápida precisamente porque es pequeña. La máquina virtual de Lua fue basada en pila hasta Lua 4.0; con Lua 5.0 pasó a estar basada en registros, lo que dio al generador de código más margen para optimizar y redujo la cantidad de instrucciones de la VM que ejecuta un programa típico. Sus diseñadores señalan que “la máquina virtual de Lua 5.0 fue la primera máquina virtual basada en registros de uso amplio”.3 La memoria la gestiona un recolector de basura incremental (introducido en Lua 5.1) que hace su trabajo en pequeños pasos en lugar de en largas pausas que detienen todo el mundo —importante para los bucles en tiempo real de un juego.3 Las pruebas de rendimiento independientes sitúan a Lua entre los más rápidos de los lenguajes de scripting interpretados, lo bastante rápido como para que, según el relato de sus diseñadores, “más del 40 % de Adobe Lightroom esté escrito en Lua”, alrededor de 100.000 líneas.3

El alcance de Lua: desde World of Warcraft hasta un robot sin sistema operativo
Súmalo todo y Lua se convirtió en la capa de scripting invisible de una porción enorme del software. En los videojuegos, World of Warcraft expone toda su interfaz a Lua para que los jugadores puedan escribir complementos; Roblox construyó Luau, un dialecto de Lua, como el lenguaje en el que millones de jóvenes creadores aprenden a programar; Dota 2, Crysis y Garry’s Mod también lo incrustan.1 Fuera de los videojuegos, Redis ejecuta scripts de Lua de forma atómica dentro de la base de datos; nginx, a través de la distribución OpenResty, usa Lua para programar el propio servidor web; Adobe Lightroom y Wireshark están construidos sustancialmente sobre él; Neovim adoptó Lua como lenguaje de configuración y de complementos de primera clase.1 Y como el intérprete es pequeño y portable, Lua llega a hardware que apenas tiene nada más —sus diseñadores cuentan el caso de Crazy Ivan, un robot ganador de la RoboCup cuyo “cerebro” ejecutaba Lua “directamente sobre un procesador Motorola Coldfire 5206e sin ningún sistema operativo; en otras palabras, Lua era el sistema operativo”.7 Un pequeño lenguaje, construido en un laboratorio de Río bajo restricciones comerciales, acabó en todas partes —porque pedía casi nada y te daba las palancas para construir el resto.
El método
Recorre DEL, SOL, la metatabla, las corrutinas y treinta años de negarse a inflar el lenguaje, y se repiten los mismos movimientos. El método de Ierusalimschy es menos un eslogan que un conjunto de compromisos permanentes.
Entrega mecanismos, no políticas. El hábito que lo define es proporcionar una palanca general y negarse a decidir cómo debe usarse. Sin sistema de clases incorporado, sin modelo fijo de concurrencia —solo tablas, metatablas y corrutinas, a partir de las cuales construyes lo que tu aplicación necesite. La lección general se transfiere mucho más allá del diseño de lenguajes: las herramientas más duraderas son las que conceden capacidad sin dictar la forma de la solución. Es lo opuesto a la “única forma obvia de hacerlo” de Guido van Rossum, y el contraste es justamente el punto —ambas son coherentes, y saber qué filosofía debería encarnar tu herramienta es la verdadera decisión.3
Mantenlo lo bastante pequeño como para que sea correcto y se pueda llevar a cualquier parte. La implementación de referencia de Lua ronda las 17.000 líneas de C limpio, un orden de magnitud más pequeña que la de otros lenguajes de scripting, y esa pequeñez es una función deliberada —es lo que hace al lenguaje incrustable, portable y fiable. La disciplina consiste en seguir recortando hasta que quitar una cosa más lo rompa, lo que convierte a Lua en el espejo, en software, del minimalismo despiadado de Sophie Wilson en ARM —despoja hasta la esencia portante y deja que la eficiencia caiga por su propio peso. Es el producto mínimo digno a nivel del entorno de ejecución de un lenguaje.3
Resiste la función que te piden hasta que encuentres el mecanismo que hay debajo. Cuando los usuarios exigieron objetos, Lua les dio semántica extensible; cuando exigieron hilos, les dio corrutinas. Cada vez, el equipo rechazó la política específica y entregó el mecanismo más general que permitía a los usuarios construir la política por sí mismos —y, lo que es crucial, no cambió de opinión años después.3 Esa es la puerta de la evidencia aplicada a las solicitudes de funciones: no añadas la cosa porque te la pidan; averigua qué problema resuelve y si un mecanismo que ya tienes puede resolverlo.
Generaliza, no acumules. La metatabla no llegó entera —creció de fallbacks a tag methods a metamétodos, y cada paso reemplazó el mecanismo anterior por uno más general en lugar de atornillar una nueva función al lado.3 La lección es evolucionar por unificación, no por adición, de modo que el lenguaje se vuelva más capaz mientras conserva el mismo tamaño —la misma economía de medios que Thompson y Ritchie usaron al construir Unix a partir de pequeñas piezas componibles.
Deja que la restricción diseñe la herramienta. Lua existe porque las barreras comerciales de Brasil obligaron a Tecgraf a construir su propio software, y su portabilidad existe porque los clientes del laboratorio usaban “una colección muy diversa de plataformas informáticas”.3 En lugar de tratar esas restricciones como desventajas, Ierusalimschy dejó que impulsaran el diseño hacia algo más pequeño, más limpio y más portable de lo que probablemente habría construido un equipo con muchos recursos —la lección de que la escasez, tomada en serio, es una herramienta de diseño y no una disculpa.3
Cadena de influencia
Quiénes lo formaron
Scheme y la tradición Lisp. Sus diseñadores son explícitos: “la influencia de Scheme sobre Lua ha aumentado gradualmente”, hasta convertirse en “una fuente de inspiración, especialmente con la introducción de funciones anónimas y el ámbito léxico completo”.3 Como Scheme, Lua es de tipado dinámico, trata las funciones como valores ordinarios de primera clase y mantiene el núcleo pequeño —la convicción de que un lenguaje puede ser potente por ser mínimo en lugar de grande. (Influencia formativa)
DEL y SOL, los dos pequeños lenguajes. Lua no surgió de la teoría; creció a partir de dos lenguajes de dominio específico construidos para Petrobras. SOL aportó la sintaxis del constructor de tablas para describir datos, y la experiencia con ambos le enseñó al equipo que “grandes partes de aplicaciones complejas podían escribirse usando lenguajes de scripting incrustables” —la constatación sobre la que, en sus palabras, descansaba el nacimiento de Lua.3 (Influencia directa)
La reserva de mercado de Brasil. Las barreras comerciales que rigieron de 1977 a 1992 son una influencia improbable pero genuina: son la razón por la que Tecgraf construyó sus propias herramientas, y la diversidad de las plataformas de sus clientes es la razón por la que la portabilidad se convirtió en un objetivo de diseño de primer orden. La política hizo el lenguaje. (Influencia formativa)
A quiénes formó él
La capa de scripting de la industria del videojuego. Desde Grim Fandango en adelante, Lua se convirtió casi en la opción por defecto para incrustar la lógica de juego, y el patrón que popularizó —motor rápido en C++, comportamiento editable en un script incrustado— es ahora práctica estándar. Luau, de Roblox, ha enseñado a programar a toda una generación de niños en un dialecto de Lua. (Influencia que define un campo)
Software embebido y de sistemas. Redis, nginx/OpenResty, Wireshark, Neovim e innumerables dispositivos adoptaron Lua como capa de scripting precisamente porque pide tan poco. Pocos lenguajes llegan desde una base de datos hasta un analizador de redes y un robot que funciona sobre el metal desnudo.
Diseñadores de lenguajes que valoran la pequeñez. Lua se erige como la prueba viviente de que un núcleo diminuto y agnóstico de paradigmas puede superar a lenguajes grandes y opinados en el nicho de la incrustación —un argumento que resuena en todo diseño de “entorno de ejecución mínimo” y de “mecanismo por encima de framework” desde entonces.
El hilo conductor
Ierusalimschy se sitúa en uno de los polos del largo argumento de esta serie sobre cuánto debería decidir una herramienta por ti. Guido van Rossum construyó Python sobre “debería haber una única forma obvia de hacerlo” y lo entregó con las pilas incluidas —el lenguaje tiene opiniones, y seguirlas es el camino de menor resistencia. Bjarne Stroustrup construyó C++ lo bastante rico como para expresar casi cualquier paradigma, pagando esa riqueza en tamaño y complejidad. Ierusalimschy fue por el camino opuesto a ambos: entrega casi ninguna política, casi ninguna función, solo unos pocos mecanismos generales y un entorno de ejecución de 17.000 líneas, y deja que el usuario construya el resto. Es el espejo, en software, de Sophie Wilson, cuyo ARM ganó por estar despojado hasta menos de 25.000 transistores —Lua es la misma pequeñez despiadada en C, y como el bajo consumo accidental de ARM, su pequeñez resultó ser justo aquello que le permitió conquistar un dominio (la incrustación) para el que nadie lo diseñó. Donde van Rossum dice aquí está la forma obvia y Stroustrup dice aquí están todas las formas, Ierusalimschy dice: aquí están las palancas —tú decides qué construir, y yo mantendré todo el conjunto lo bastante pequeño como para llevarlo a cualquier parte. (Puente de la serie)
Lo que me llevo de esto
La lección que conservo de Ierusalimschy es que lo más fuerte que puedes entregarle a alguien es un mecanismo, no una política. Es tentador, cuando construyes una herramienta, hornear dentro tu opinión sobre cómo debería usarse —entregar el sistema de clases, el framework, el único flujo de trabajo bendecido. Toda la trayectoria de Lua es un argumento de que lo contrario envejece mejor. Al negarse a fijar un modelo de objetos y entregar la metatabla en su lugar, el lenguaje permitió a los usuarios construir esquemas de herencia que sus diseñadores nunca imaginaron, en videojuegos, bases de datos y editores que nunca anticiparon. Cuando construyo algo ahora, la pregunta que tomo prestada de Lua es si estoy entregando una decisión o una capacidad —porque la decisión sirve a los casos que puedo ver hoy, y la capacidad sirve a los que no puedo ver.
La segunda lección es que la pequeñez no es una restricción que toleras —es una función que proteges. Habría sido fácil, a lo largo de treinta años de presión de los usuarios, dejar que Lua creciera hasta ser un lenguaje grande con una palabra clave class, una biblioteca de hilos y un framework estándar para todo. El equipo se negó, y la negativa es la razón por la que Lua cabe en un disquete, compila en todas partes y se incrusta en el cerebro de metal desnudo de un robot. La disciplina de seguir siendo pequeño —de generalizar en lugar de acumular, de rechazar la función hasta encontrar el mecanismo que hay debajo— es más difícil que la disciplina de añadir, y mucho más valiosa. Es la calidad es la única variable leída como contención: la cosa pequeña correcta, defendida durante décadas, se convierte en la infraestructura sobre la que todo lo demás puede apoyarse.
Preguntas frecuentes
¿Quién es Roberto Ierusalimschy y qué creó?
Roberto Ierusalimschy es un informático brasileño, nacido en 1960 en Río de Janeiro y catedrático de informática en la PUC-Rio. Es el diseñador principal de Lua, el lenguaje de scripting pequeño, rápido e incrustable que creó en 1993 en el laboratorio Tecgraf de la PUC-Rio junto a Luiz Henrique de Figueiredo y Waldemar Celes. También es autor del libro Programming in Lua y creador de LPeg, una biblioteca de coincidencia de patrones, y coautor de la historia primaria del lenguaje, “The Evolution of Lua”.356
¿Qué significa “mecanismos, no políticas” en Lua?
Significa que Lua te da unos pocos mecanismos potentes y generales en lugar de imponer decisiones fijas. El ejemplo más claro es la orientación a objetos: Lua no tiene un sistema de clases incorporado. En cambio, ofrece tablas (que pueden contener tanto datos como métodos) y metatablas (que te permiten personalizar cómo se comporta una tabla), y tú mismo construyes la herencia, las clases o cualquier otro modelo de objetos. Sus diseñadores escribieron que “Lua no impone ningún modelo de objetos o de clases al programador” y eligieron “proporcionar mecanismos flexibles” en su lugar —una postura que han mantenido desde 1993.3
¿Por qué se usa Lua tan ampliamente en videojuegos y sistemas embebidos?
Porque fue diseñado desde el principio para ser pequeño, rápido, portable y fácil de incrustar. La implementación de referencia ronda las 17.000 líneas de C ANSI limpio que compila casi en cualquier parte, el intérprete compilado pesa aproximadamente 143 KB, y una API de C bien definida permite que un programa anfitrión lo controle por completo. Ese perfil es exactamente lo que necesita un motor de juego o un dispositivo embebido —trabajo pesado en C/C++, lógica editable en pequeños scripts— y por eso programa World of Warcraft, Roblox (mediante Luau), Redis, nginx/OpenResty, Adobe Lightroom y dispositivos que llegan hasta robots de metal desnudo.137
¿De dónde vino el nombre “Lua”?
Lua significa “luna” en portugués. Se nombró así como sucesor de un lenguaje anterior de Tecgraf llamado SOL —“Simple Object Language”, y también “sol” en portugués. Un colega de Tecgraf, Carlos Henrique Levy, sugirió el nombre “Lua” para el nuevo lenguaje, completando la progresión de sol a luna. Todo el proyecto creció a partir de dos pequeños lenguajes, DEL y SOL, construidos para la petrolera brasileña Petrobras.3
Fuentes
-
“Lua (programming language),” Wikipedia. Lua fue creado en 1993 por Roberto Ierusalimschy, Luiz Henrique de Figueiredo y Waldemar Celes en el Grupo de Tecnología en Computación Gráfica (Tecgraf) de la Pontificia Universidad Católica de Río de Janeiro (PUC-Rio), Brasil; implementado en C ANSI, con licencia MIT, con una máquina virtual basada en registros desde Lua 5.0, recolección de basura, corrutinas y funciones de primera clase. Las implementaciones de referencia recientes siguen siendo pequeñas (el artículo señala que Lua 5.5.0 comprende aproximadamente 32.000 líneas de C). Entre los usuarios documentados están los videojuegos World of Warcraft, Roblox (que desarrolló Luau, un derivado de Lua), Dota 2, Crysis y Garry’s Mod, y software ajeno a los juegos como Redis, nginx (mediante OpenResty), Adobe Lightroom, Wireshark y Neovim. ↩↩↩↩
-
“Roberto Ierusalimschy: Known for Lua Programming Language,” machaddr (perfil biográfico). Resume el papel de Ierusalimschy como creador y arquitecto principal de Lua, desarrollado con Luiz Henrique de Figueiredo y Waldemar Celes en la PUC-Rio, lanzado por primera vez en 1993; señala el uso mundial de Lua en software como World of Warcraft y Adobe Lightroom, su autoría de Programming in Lua y su creación de la biblioteca LPeg. ↩
-
Roberto Ierusalimschy, Luiz Henrique de Figueiredo y Waldemar Celes, “The Evolution of Lua,” Proceedings of the Third ACM SIGPLAN Conference on the History of Programming Languages (HOPL III), 2007. Fuente primaria. “Lua es un lenguaje de scripting nacido en 1993 en la PUC-Rio.” “Desde el principio, Lua se diseñó para ser simple, pequeño, portable, rápido y fácilmente incrustable en aplicaciones.” La única estructura de datos: “ofrece un único tipo de estructura de datos, la tabla.” Implementado en “C limpio”, “la intersección entre C y C++”, y “compila sin más en la mayoría de las plataformas”. Tamaño pequeño: el código fuente de Lua 5.1 ronda las “17.000 líneas de C”, el tarball “cabe cómodamente en un disquete” y “el intérprete de Lua construido con todas las bibliotecas estándar de Lua ocupa 143K”. “más del 40 % de Adobe Lightroom está escrito en Lua (eso representa alrededor de 100.000 líneas de código Lua).” Sobre la política comercial de Brasil: “Desde 1977 hasta 1992, Brasil tuvo una política de fuertes barreras comerciales (llamada ‘reserva de mercado’) para el hardware y el software informáticos”, y “esas razones llevaron a Tecgraf a implementar desde cero las herramientas básicas que necesitaba”; Lua es “el único lenguaje creado en un país en desarrollo que ha alcanzado relevancia global”. Predecesores DEL (“data-entry language”) y SOL (“Simple Object Language”). El nombre: SOL es sol en portugués, y “un amigo en Tecgraf (Carlos Henrique Levy) sugirió el nombre ‘Lua’ (luna en portugués), y Lua nació”. Primera implementación terminada en julio de 1993 siguiendo “la cosa más simple que pudiera funcionar”. Sobre “mecanismos, no políticas”: “no quisimos convertir Lua en un lenguaje orientado a objetos porque no queríamos fijar un paradigma de programación para Lua”; “Lua no impone ningún modelo de objetos o de clases al programador”; “decidimos proporcionar mecanismos flexibles que permitieran al programador construir el modelo que resultara adecuado para la aplicación”; “La semántica extensible se ha convertido en un sello distintivo de Lua”. Evolución del mecanismo: fallbacks (Lua 2.1, 1995) → tag methods (Lua 3.0, 1997) → metatablas y metamétodos (Lua 5.0, 2003); los fallbacks de indexación de tablas soportaban “muchas formas de herencia (mediante delegación)”; el término “metatabla” fue sugerido por Rici Lake en 2001. Lua como “un lenguaje de extensión extensible” con una API de C que permite “la comunicación plena entre el código Lua y el código externo”. Videojuegos: en enero de 1997, Bret Mogilefsky, programador principal de Grim Fandango de LucasArts, reportó que “una cantidad tremenda del juego estaba escrita en Lua”, tras lo cual “Lua se difundió de boca en boca entre los desarrolladores de videojuegos hasta convertirse en una habilidad definitivamente comercializable en la industria del videojuego”. Concurrencia: implementar hilos preemptivos requiere primitivas “que no forman parte de ANSI C”, y “no creíamos (y seguimos sin creer) en el modelo estándar de multithreading… nadie puede escribir programas correctos en un lenguaje en el que ‘a=a+1’ no es determinista”; la multitarea cooperativa mediante corrutinas se proporcionó en Lua 5.0 (2003). VM: “Desde Lua 5.0, la máquina virtual está basada en registros”, y “la máquina virtual de Lua 5.0 fue la primera máquina virtual basada en registros de uso amplio”; la recolección de basura incremental aparece en Lua 5.1. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩
-
“Lua: about,” Lua.org (sitio oficial). “Lua es un lenguaje de scripting potente, eficiente, ligero e incrustable.” “Se implementa como una pequeña biblioteca de funciones de C, escrita en C limpio, el subconjunto común del C estándar y C++”, y “se ejecuta en toda clase de sistemas Unix y Windows, así como en dispositivos móviles… microprocesadores embebidos… y mainframes de IBM.” Describe Lua como una combinación de “una sintaxis procedimental simple con potentes construcciones de descripción de datos basadas en arreglos asociativos y semántica extensible”, con tipado dinámico, gestión automática de memoria con recolección de basura incremental, y siendo “rápido” y “portable”. ↩↩
-
“Roberto Ierusalimschy,” Wikipedia, corroborado por su “perfil docente,” Departamento de Informática, PUC-Rio. Nacido el 21 de mayo de 1960 en Río de Janeiro, Brasil; doctorado en ciencias de la computación por la PUC-Rio (1990); catedrático de informática en la PUC-Rio; trabajo posdoctoral en la Universidad de Waterloo y profesor visitante en Stanford (2012). Creador y arquitecto principal del lenguaje de programación Lua, autor de Programming in Lua (cuatro ediciones), y desarrollador de LPeg, una biblioteca de Lua para implementar gramáticas de expresión de análisis sintáctico. ↩↩
-
“Programming in Lua,” por Roberto Ierusalimschy, Lua.org. El libro oficial sobre Lua, escrito por su diseñador principal, que describe el diseño y el uso del lenguaje; la primera edición está disponible gratuitamente en línea. Refuerza el diseño de Lua en torno a las tablas como único mecanismo de estructuración de datos, las metatablas para el comportamiento extensible, las funciones de primera clase y las corrutinas para la multitarea cooperativa. ↩
-
Roberto Ierusalimschy, Luiz Henrique de Figueiredo y Waldemar Celes, “The Evolution of Lua,” HOPL III, 2007, nota al pie sobre el uso embebido. “Crazy Ivan, un robot que ganó la RoboCup en 2000 y 2001 en Dinamarca, tenía un ‘cerebro’ implementado en Lua. Lua se ejecutaba directamente sobre un procesador Motorola Coldfire 5206e sin ningún sistema operativo (en otras palabras, Lua era el sistema operativo). Lua se almacenaba en una ROM del sistema y cargaba programas al arrancar desde el puerto serie.” Ilustra el alcance de Lua hasta dispositivos embebidos de metal desnudo, consecuencia de su implementación pequeña y portable. ↩↩↩