7 puntos por GN⁺ 2025-09-23 | 1 comentarios | Compartir por WhatsApp
  • Luau es un lenguaje de scripting embebido derivado de Lua 5.1, rápido, seguro y con soporte para tipado gradual
  • Evolucionó reforzando el rendimiento, las herramientas del lenguaje y el sistema de tipos para soportar juegos complejos y bases de código grandes en la plataforma Roblox
  • A diferencia de Lua base, está diseñado con funciones de sandboxing para que código con distintos niveles de privilegios pueda ejecutarse en paralelo
  • Su sintaxis es compatible con Lua 5.1, pero ofrece extensiones sintácticas adicionales y herramientas de análisis (linter, verificador de tipos) para mejorar la calidad del código
  • Con optimizaciones de rendimiento, bytecode personalizado y soporte JIT, busca velocidades de ejecución al nivel de LuaJIT, y tiene un gran potencial de uso más allá de Roblox en diversos entornos embebidos

Motivation (motivación)

  • Alrededor de 2006, Roblox adoptó Lua 5.1 como lenguaje de scripting para juegos
  • Con el paso del tiempo, a medida que subió el nivel de los juegos en la plataforma Roblox y crecieron los equipos, mejoraron profundamente el lenguaje y su implementación para superar las limitaciones de Lua existente
  • Junto con el crecimiento de la plataforma, invirtieron mucho en optimización de rendimiento, facilidad de uso y desarrollo de herramientas relacionadas con el lenguaje
  • En particular, al administrar para 2020 una base de código a gran escala de más de un millón de líneas, reconocieron que introducir un sistema de tipos gradual era indispensable
  • Con base en esas necesidades, Roblox desarrolló Luau, un lenguaje derivado de Lua que ofrece velocidad, tamaño reducido, seguridad y la capacidad de aplicar tipos de forma gradual
  • Más detalles están disponibles en el documento Why Luau

Resumen de Luau

  • Luau es un lenguaje de scripting embebido basado en Lua 5.1
    • Ofrece un runtime rápido y ligero
    • Soporta un sistema de tipos gradual, lo que permite combinar análisis dinámico y estático
  • Está integrado en Roblox Studio, y se puede activar el modo estricto con la bandera --!strict
  • Los desarrolladores pueden consultar la documentación vinculada con Roblox en Luau Creator Docs

Sandboxing (sandbox)

  • Luau restringe la biblioteca estándar expuesta y ofrece funciones adicionales de sandboxing
  • Esto permite ejecutar en paralelo de forma segura tanto código sin privilegios escrito por desarrolladores comunes como código privilegiado interno de la plataforma
  • Por ello, su entorno de ejecución es distinto al de Lua base
  • Los detalles están disponibles en la explicación de Sandbox

Compatibility (compatibilidad)

  • Mantiene, en la medida de lo posible, la compatibilidad hacia atrás con Lua 5.1, e incorpora también algunas funciones de versiones posteriores
  • Sin embargo, Luau no adopta todas las decisiones de diseño de Lua, ya que refleja casos de uso y restricciones propios de Roblox
  • El estado del soporte para funciones de versiones posteriores a Lua 5.1 se detalla en el documento de Compatibility

Syntax (sintaxis)

  • Es totalmente compatible con la sintaxis de Lua 5.1
  • Además, ofrece extensiones sintácticas modernas y familiares para facilitar el desarrollo
  • La sintaxis completa puede consultarse en el documento de Syntax

Analysis (herramientas de análisis)

  • Proporciona herramientas de análisis de scripts para ayudar a escribir código correcto

  • Componentes:

    • Linter: detecta errores comunes
    • Type Checker: valida tipos
  • Puede ejecutarse con la herramienta de línea de comandos luau-analyze

  • Las reglas de lint están en el documento de Lint, y la guía de verificación de tipos en Typecheck

Performance (rendimiento)

  • Ofrece un frontend personalizado con parser, linter y verificador de tipos, además de bytecode optimizado, intérprete y compilador
  • En algunos casos, ofrece un rendimiento capaz de competir con el intérprete de LuaJIT
  • Soporta un compilador JIT manual en plataformas x64 y ARM64, lo que puede mejorar mucho el rendimiento de ciertos programas
  • El runtime se sigue optimizando y algunas partes se están reescribiendo para mejorar la eficiencia
  • Los detalles de rendimiento están disponibles en el documento de Performance

Libraries (bibliotecas)

  • El lenguaje en sí es un superconjunto completo de Lua 5.1
  • En la biblioteca estándar se eliminan algunas funciones y se agregan otras nuevas
  • Cuando se integra en una aplicación, también puede acceder a bibliotecas de extensión específicas de la app
  • La documentación completa de bibliotecas puede consultarse en el documento de Library

1 comentarios

 
GN⁺ 2025-09-23
Opiniones de Hacker News
  • En Lumix Engine usaban Lua y LuaJIT, pero se cambiaron a Luau por el sistema de tipos. Aun así, sintieron que es difícil usarlo fuera de Roblox; la documentación es pobre y casi no hay comunidad, así que no ayuda en nada a resolver problemas. Comparado con Lua o LuaJIT, el tamaño es mayor y la compilación es 7 veces más lenta. El manejo asíncrono de la API en la práctica queda bloqueado de forma sincrónica, y también hay varias incomodidades, como el uso de STL. Además, se topan seguido con bugs de análisis y del LSP. Por eso están pensando en buscar otra alternativa.
    • El equipo de Roblox está enfocándose en que Luau sea más fácil de usar también fuera de Roblox en el futuro. Ya se usa bien en varios lugares, como Remedy Entertainment (Alan Wake 2), Digital Extremes (Warframe) y GIANTS Software (Farming Simulator 25). Hasta ahora la inversión y el soporte habían estado concentrados dentro de Roblox, pero ahora están desarrollando Lute, un runtime independiente de propósito general. También quieren ampliar el ecosistema creando varias herramientas de desarrollo basadas en Luau. Aún está en una etapa temprana, pero están invirtiendo activamente para apoyar el uso externo y distintos casos de uso. Creen que, para el crecimiento saludable de Luau, es importante atraer a más usuarios y casos de uso diversos.
    • Están usando Luau para todo el código de gameplay de un juego en Unity (más de 60 mil líneas). Les gustaría que se reforzara la documentación, especialmente lo relacionado con integraciones personalizadas, y sienten que el nuevo sistema de tipos y el LSP todavía no encajan del todo bien. Desde que zeux dejó el equipo, les preocupa un poco la dirección a largo plazo. Aun así, la experiencia de desarrollo en sí les gusta mucho: el código de Luau se recarga en caliente casi al instante incluso mientras el juego está corriendo, y los proyectos en C++ también compilan rápido. También les gusta que ofrezca un entorno sandbox para dar soporte a mods. La comunidad oficial en Discord también es bastante activa.
    • Dijeron que la compilación se volvió más lenta, pero si es un lenguaje de scripting, ¿no se supone que no hace falta compilar el código? Preguntan si quizá se refieren a la compilación de la VM de Luau en sí.
  • Es realmente interesante que Roblox esté desarrollando un runtime de Luau para escritorio al estilo Node.js: https://github.com/luau-lang/lute
    • Ya existe un runtime de Luau más maduro, Lune. Lo usan para scripts de build y automatización de archivos place de Roblox, y para sus necesidades funciona de forma bastante satisfactoria.
    • Existe otro runtime independiente de Luau, Lune.
  • Luau parece mucho más complejo que Lua. Viendo el código, Luau tiene 120 mil líneas en C++, mientras que Lua 5.1 tiene 14 mil líneas en C. Piensan que, al meter un sistema de tipos gradual o estático, es inevitable que se vuelva más complejo. Si hay un sistema de tipos medianamente completo, al final inevitablemente va a ser más grande que un lenguaje de scripting dinámico.
    • Lua (y hasta cierto punto Luau) es pequeño no tanto por la cantidad de líneas de código, sino al momento de aprender el lenguaje en sí. El runtime necesario para ejecutar no depende por completo de Analysis. En Analysis hay dos sistemas de tipos completos, y durante los últimos 3 años han estado desarrollando uno nuevo para resolver limitaciones fundamentales; pronto planean retirar el antiguo. Cuando eso pase, podrían reducir el código en unas 30 mil líneas.
    • Yo no diría que Lua y Luau sean lenguajes pequeños o simples. Puede que esa complejidad no sea necesariamente indispensable. Estoy trabajando en un lenguaje más simple pero expresivo llamado Bau, y también en una VM de estilo Lua. Este tipo de lenguajes pequeños aparece seguido en Reddit: Bau, Bau VM, r/ProgrammingLanguages
    • El tipado estático o gradual sí aumenta la complejidad, pero el incremento es más pequeño de lo que parece. De hecho, a veces un lenguaje de scripting dinámico puede ser más complejo. Un type checker Hindley–Milner se puede implementar en una sola página de código; esta complejidad de unas 2 mil páginas de la que estamos hablando se siente excesiva. H–M es completo incluso sin manejar funciones de orden superior, genéricos (polimorfismo paramétrico) ni punteros nulos, y permite inferencia total. También se puede extender, y aun en su forma básica es mucho más potente que los sistemas de tipos de C o Java 1.7.
    • Yo mismo escribí un type checker para Lua y también he leído mucho de su código fuente. Las 14 mil líneas de Lua tienen una densidad de código muy alta; si estuviera escrito con un estilo más común, serían unas 30-40 mil líneas. O sea, Lua no es esencialmente pequeño, sino que está escrito de forma extremadamente concisa.
    • Si se desglosan más las líneas analizadas con tokei: el directorio Analysis tiene 62 mil líneas de C++, 9,200 líneas de headers en C; Ast tiene 8,400 líneas de C++; CodeGen tiene 21 mil líneas de C++, etc. Lua 5.1, en todo src, tiene 11 mil líneas de código C y 1,900 líneas de headers.
  • Tienen curiosidad por la diferencia entre Teal y Luau. Ambos se presentan como “dialectos de Lua con tipado estático”, así que quieren compararlos: https://teal-language.org/
    • Teal compila archivos Teal a Lua, así que aplican tanto las ventajas como las desventajas de una relación como la de JS y TS. Luau, en cambio, tiene su propio runtime compatible hacia arriba con Lua, y no solo mejora el sistema de tipos sino también la experiencia de desarrollo en general. Por eso son bastante distintos. Teal tiene la ventaja de poder usar Lua en cualquier lado; Luau, en cambio, solo corre en un runtime específico de Luau, pero como no requiere una etapa separada de compilación, desde la perspectiva del desarrollador puede ofrecer mejor usabilidad. Además, la información de tipos no se pierde y se puede aprovechar.
    • Teal transpila a Lua, mientras que Luau es un fork de Lua. Puede cambiar ampliamente en rendimiento del intérprete, seguridad, extensibilidad de sintaxis, etc. Roblox es lo bastante grande como para rondar los 100 mil millones de dólares de capitalización bursátil y tiene varios desarrolladores dedicados trabajando en esto.
    • Luau no es simplemente “Lua con tipos”, sino que apuesta fuerte por un sistema de tipos gradual y por la inferencia de tipos, al mismo tiempo que va mejorando el lenguaje de manera gradual. Está diseñado con foco en la experiencia del desarrollador y el soporte de herramientas; se preocupan por cosas como el tamaño del binario, pero no priorizan la simplicidad estricta al estilo de Lua. Está más enfocado en dar una buena experiencia a quienes programan directamente en el lenguaje que en servir para atar grandes proyectos en C a Lua.
  • Da pena que Lua no haya podido evolucionar manteniendo mejor la compatibilidad con versiones anteriores. A fines de los 2000, varios proyectos, incluido Roblox, adoptaron Lua 5.1, y hoy Lua ya va por 5.4, pero la compatibilidad con versiones viejas no se mantuvo bien. LuaJIT, por ejemplo, solo soporta 5.1. Se parece a la situación de Python 2.x/3.x, pero en la comunidad de Lua la mayoría tiende a seguir usando 5.1.
    • En realidad es peor: luau y luaJIT también evolucionaron en direcciones distintas al proyecto oficial de lua, y ahora ya no son sutilmente compatibles entre sí. Todos se separaron desde Lua 5.1, pero da la impresión de que ya no existe un estándar oficial real.
    • La gran diferencia es que la comunidad de Lua no critica abiertamente el mantenimiento de compatibilidad hacia atrás, así que es bastante fácil escribir código para distintas versiones.
    • Es difícil conseguir estadísticas oficiales, pero por sensación parece que hay más usuarios de 5.1 y 5.2 que de 5.4, y que 5.3 tampoco la supera. LuaJIT genera mucho interés, pero en la práctica no se ve tan seguido.
    • LuaJIT también incluye algunas funciones de versiones más recientes de Lua (5.2, 5.3) y agrega todavía más extensiones: https://luajit.org/extensions.html
  • Lo más interesante fue que el intérprete de Luau a veces puede competir con LuaJIT. La página de rendimiento lo explica muy bien y deja ver la capacidad de ingeniería de Roblox: https://luau.org/performance
  • Conocieron Luau porque su hijo de 13 años empezó a interesarse en Roblox Studio, y también visitaron luau.org. La ingeniería de Roblox realmente impresiona.
    • Arseny Kapoulkine es un ingeniero sobresaliente. Vale la pena seguir su blog o redes sociales. Además de luau y del motor de render de Roblox, creó meshoptimizer, una librería que en la industria gráfica casi es de uso obligatorio, y volk está incluso incluido en el Vulkan SDK.
  • Second Life está en proceso de migrar desde Linden Scripting Language a Luau. Antes usaban compilación basada en Mono, pero como Mono ya no se mantiene, necesitaban un lenguaje nuevo. No solo añadieron soporte para Luau, sino que también cambiaron el compilador existente de LSL para que apunte al motor de ejecución de Luau. El rendimiento también mejoró un poco. Second Life tiene un entorno particular donde corren en el servidor cientos de miles de scripts basados en eventos, así que administrar recursos no es sencillo; si programas inactivos consumen 1 microsegundo por frame, la suma puede convertirse en un problema serio.
    • Cuando abrieron el entorno beta de Luau, lo probaron directamente y sintieron una mejora de rendimiento grande frente al sistema anterior basado en Mono. En particular, al guardar (Save), la velocidad de verificación del script pasó de 10 segundos a ser instantánea, lo que mejoró mucho la productividad. Aun así, les gustaría que hubiera funciones helper como CreateThread(fn), Wait(ms) y soporte de Await/Promises como en FiveM, para manejar corrutinas más cómodamente (implementación de Luau Promise). En FiveM, este tipo de wrappers facilita la optimización de scripts y la administración de corrutinas: ejemplo del scheduler Lua de FiveM
    • Lo que se nota de inmediato al cambiar la VM es que buena parte del overhead anterior estaba en el scheduling, los cambios de contexto y la implementación de funciones de librería. Luau, por diseño, soporta de forma natural el scheduling preventivo, así que coordinar código glue simple se vuelve mucho más fácil. Resolver esto a nivel de VM es mucho más barato y sencillo que transformar estados en el AST o en la etapa de bytecode. Incluso ese overhead de microsegundos de los programas idle es algo que, al final, el scheduler debe optimizar.
  • Parte del encanto minimalista original de Lua se ha visto afectado por la inferencia de tipos, aunque es un intercambio con la seguridad de tipos, así que tiene sus pros y contras. Pero les desconcertó que, incluso declarando --!strict, el código se ejecutara sin ningún error ni advertencia aun cuando había violaciones de tipos evidentes. No era el comportamiento que esperaban.
    • Actualmente el sistema de tipos de Luau no es “obligatorio (strict)”. Se puede ejecutar código sin type checking, y si lo ejecutas directamente con la demo o con el binario luau, la verificación de tipos no se aplica. Si en un entorno embebido se obliga a que todo el código pase por type checking antes de compilarse, entonces sí se obtiene la experiencia esperada de detectar errores de tipos. Es un diseño inevitable, dado que se migraron de golpe cientos de millones de líneas de código de Lua 5.1 a Luau.
  • Siempre quisieron Typed Lua, pero implementar por completo un type checker y un LSP para un lenguaje dinámico era bastante difícil. Cada lenguaje dinámico tiene problemas parecidos de tipado estructural, similares a los que se ven en TypeScript. Se preguntan si, reutilizando el engine de TypeScript, convirtiendo parcialmente código Luau a TypeScript, verificándolo con tsc y luego mapeando de vuelta los errores y resultados a Luau, no se podría crear rápidamente un type checker para distintos lenguajes dinámicos.
    • Así como LLVM sirve como IR común para compiladores, también podría existir algo como un “lenguaje intermedio” para sistemas de tipos, usando el sistema de tipos de TypeScript como backend común. No prefiero los lenguajes dinámicos, pero si pudieran tener verificación de tipos y soporte de herramientas al nivel de TypeScript, me interesarían mucho más. Lo que no se pueda cubrir, se deja pasar; al final esa es la esencia del tipado gradual. Si el sistema de tipos de TypeScript llegara a un runtime de Lua, sin duda lo probaría. También me interesa mucho la dirección que está tomando Luau.
    • Luau ya tiene un excelente Luau Language Server, así que en vscode, nvim, zed, etc., ofrece diagnósticos sobresalientes, autocompletado y type checking estricto. La experiencia de desarrollo es mucho mejor de lo que sentí con Ruby o Python. Yo uso Luau tanto para shell scripting como para programación general, y hasta hice mi propio runtime estilo node llamado seal. Dicen que los desarrolladores de Roblox usan más Lune para CI/CD, testing y cosas similares.
    • Si se intenta tipar con TypeScript hasta los rincones más raros de un lenguaje dinámico, el sistema se vuelve demasiado complejo; por eso piensan que es mejor poner ciertas restricciones al lenguaje objetivo y usar un sistema de tipos Hindley–Milner, como hacen Rescript o Gleam. Los sistemas HM son sólidos y prácticos gracias a décadas de experiencia y teoría acumulada. Personalmente les sorprende que no exista un pequeño proyecto de lenguaje tipo ML que emita código Lua. Si Gleam tuviera backend para Lua, encajaría muy bien.
    • Ya existe un proyecto así: TypeScriptToLua. Lo usaron en Love2D y la experiencia fue bastante buena.