Lua (lenguaje de programación)
Lua (LOO-ə; del portugués: lua [ˈlu.(w)ɐ] que significa luna) es un lenguaje de programación ligero, de alto nivel y multiparadigma diseñado principalmente para uso integrado en aplicaciones. Lua es multiplataforma, ya que el intérprete del código de bytes compilado está escrito en ANSI C, y Lua tiene una API de C relativamente simple para integrarlo en las aplicaciones.
Lua se originó en 1993 como un lenguaje para extender aplicaciones de software para satisfacer la creciente demanda de personalización en ese momento. Proporcionó las instalaciones básicas de la mayoría de los lenguajes de programación de procedimientos, pero no se incluyeron características más complicadas o específicas del dominio; más bien, incluía mecanismos para extender el lenguaje, lo que permitía a los programadores implementar tales funciones. Como Lua estaba destinado a ser un lenguaje de extensión integrable general, los diseñadores de Lua se centraron en mejorar su velocidad, portabilidad, extensibilidad y facilidad de uso en el desarrollo.
Historia
Lua fue creada en 1993 por Roberto Ierusalimschy, Luiz Henrique de Figueiredo y Waldemar Celes, miembros del Grupo de Tecnología de Gráficos por Computador (Tecgraf) de la Pontificia Universidad Católica de Río de Janeiro, en Brasil.
Desde 1977 hasta 1992, Brasil tuvo una política de fuertes barreras comerciales (llamada reserva de mercado) para hardware y software de computadora. En ese ambiente, los clientes de Tecgraf no podían permitirse, ni política ni financieramente, comprar software personalizado en el extranjero. Esos motivos llevaron a Tecgraf a implementar desde cero las herramientas básicas que necesitaba.
Los predecesores de Lua fueron los lenguajes de descripción/configuración de datos SOL (lenguaje de objetos simples) y DEL (lenguaje de entrada de datos). Se habían desarrollado de forma independiente en Tecgraf en 1992-1993 para agregar cierta flexibilidad a dos proyectos diferentes (ambos eran programas gráficos interactivos para aplicaciones de ingeniería en la empresa Petrobras). Había una falta de estructuras de control de flujo en SOL y DEL, y Petrobras sintió una necesidad creciente de agregarles un poder de programación completo.
En La evolución de Lua, los autores del idioma escribieron:
En 1993, el único contendiente real era Tcl, que se había diseñado explícitamente para integrarse en aplicaciones. Sin embargo, Tcl tenía sintaxis desconocida, no ofreció un buen apoyo para la descripción de datos, y sólo funcionó en plataformas Unix. No consideramos LISP o Scheme debido a su sintaxis inapropiada. Python todavía estaba en su infancia. En la atmósfera libre, do-it-yourself que entonces reinaba en Tecgraf, era bastante natural que deberíamos tratar de desarrollar nuestro propio lenguaje de scripting... Debido a que muchos usuarios potenciales del lenguaje no eran programadores profesionales, el idioma debe evitar la sintaxis críptica y la semántica. La implementación del nuevo lenguaje debe ser altamente portátil, porque los clientes de Tecgraf tenían una colección muy diversa de plataformas informáticas. Por último, ya que esperamos que otros productos de Tecgraf también necesiten incrustar un lenguaje de scripting, el nuevo idioma debe seguir el ejemplo de SOL y ser proporcionado como biblioteca con una API de C.
Lua 1.0 fue diseñado de tal manera que sus constructores de objetos, siendo ligeramente diferentes del estilo ligero y flexible actual, incorporaron la sintaxis de descripción de datos de SOL (de ahí el nombre Lua: Sol que significa "Sol" en portugués, y Lua que significa "Luna"). La sintaxis de Lua para las estructuras de control se tomó prestada principalmente de Modula (if
, while
, repeat
/until
), pero también había tomado influencia de CLU (asignaciones múltiples y múltiples retornos de llamadas a funciones, como una alternativa más simple a los parámetros de referencia o punteros explícitos), C++ ("buena idea de permitir que una variable local se declare solo donde la necesitamos"), SNOBOL y AWK (matrices asociativas). En un artículo publicado en Dr. Dobb's Journal, los creadores de Lua también afirman que LISP y Scheme con su único mecanismo de estructura de datos ubicuo (la lista) fueron una gran influencia en su decisión de desarrollar la tabla como el principal estructura de datos de Lua.
La semántica de Lua se ha visto cada vez más influenciada por Scheme a lo largo del tiempo, especialmente con la introducción de funciones anónimas y alcance léxico completo. Se agregaron varias características en las nuevas versiones de Lua.
Las versiones de Lua anteriores a la versión 5.0 se publicaron con una licencia similar a la licencia BSD. Desde la versión 5.0 en adelante, Lua se ha licenciado bajo la Licencia MIT. Ambas son licencias permisivas de software libre y son casi idénticas.
Características
Lua se describe comúnmente como un "paradigma múltiple" lenguaje, proporcionando un pequeño conjunto de características generales que se pueden ampliar para adaptarse a diferentes tipos de problemas. Lua no contiene soporte explícito para la herencia, pero permite que se implemente con metatablas. De manera similar, Lua permite a los programadores implementar espacios de nombres, clases y otras características relacionadas utilizando su implementación de tabla única; las funciones de primera clase permiten el empleo de muchas técnicas de programación funcional; y el alcance léxico completo permite ocultar información detallada para hacer cumplir el principio de privilegio mínimo.
En general, Lua se esfuerza por proporcionar metafunciones sencillas y flexibles que puedan ampliarse según sea necesario, en lugar de proporcionar un conjunto de funciones específico para un paradigma de programación. Como resultado, el lenguaje base es ligero (el intérprete de referencia completo tiene solo unos 247 kB compilados) y se adapta fácilmente a una amplia gama de aplicaciones.
Un lenguaje escrito dinámicamente diseñado para usarse como lenguaje de extensión o lenguaje de secuencias de comandos, Lua es lo suficientemente compacto como para caber en una variedad de plataformas host. Solo admite una pequeña cantidad de estructuras de datos atómicos, como valores booleanos, números (coma flotante de doble precisión y enteros de 64 bits de forma predeterminada) y cadenas. Las estructuras de datos típicas, como matrices, conjuntos, listas y registros, se pueden representar utilizando la estructura de datos nativa única de Lua, la tabla, que es esencialmente una matriz asociativa heterogénea.
Lua implementa un pequeño conjunto de funciones avanzadas, como funciones de primera clase, recolección de elementos no utilizados, cierres, llamadas de seguimiento adecuadas, coerción (conversión automática entre cadenas y valores numéricos en tiempo de ejecución), rutinas (multitarea cooperativa) y carga dinámica de módulos..
Sintaxis
El clásico "¡Hola, mundo!" programa se puede escribir de la siguiente manera:
impresión()"¡Hola, Mundo!")
o como:
impresión ¡Hola, Mundo! '
Un comentario en Lua comienza con un guión doble y se extiende hasta el final de la línea, similar a Ada, Eiffel, Haskell, SQL y VHDL. Las cadenas de varias líneas y los comentarios están adornados con corchetes dobles.
La función factorial se implementa como una función en este ejemplo:
función factorial()n) local x = 1 para i = 2, n do x = x * i final retorno xfinal
Flujo de control
Lua tiene un tipo de prueba condicional: if then end
con construcciones de control de ejecución opcionales else
y elseif then
.
La declaración genérica if then end
requiere las tres palabras clave:
si condición entonces- cuerpo de estadofinal
La palabra clave else
se puede agregar con un bloque de declaración adjunto para controlar la ejecución cuando la condición if
se evalúa como false
:
si condición entonces- cuerpo de estadomás- cuerpo de estadofinal
La ejecución también se puede controlar de acuerdo con múltiples condiciones utilizando las palabras clave elseif then
:
si condición entonces- cuerpo de estadosi condición entonces- cuerpo de estadomás - Opcional--optional default statement bodyfinal
Lua tiene cuatro tipos de bucles condicionales: el bucle while, el bucle repeat
(similar a un bucle do while), el bucle numérico for y el bucle genérico for
círculo.
--condición = verdadmientras condición do - Estadosfinalrepetición - Estadoshasta condiciónpara i = primero, último, delta do --delta puede ser negativa, permitiendo que el bucle para contar abajo o arriba - Estados --ejemplo: print(i)final
El bucle genérico for
:
para clave, valor dentro pares()G.) do impresión()clave, valor)final
iteraría sobre la tabla _G
utilizando la función iteradora estándar pairs
, hasta que devuelva nil
.
Los bucles también se pueden anidar (colocar dentro de otro bucle).
local cuadrícula = {} {} 11, 12, 13 } {} 21, 22, 23 } {} 31, 32, 33 }}para Sí., fila dentro pares()cuadrícula) do para x, valor dentro pares()fila) do impresión()x, Sí., valor) finalfinal
Funciones
El tratamiento de Lua de las funciones como valores de primera clase se muestra en el siguiente ejemplo, donde se modifica el comportamiento de la función de impresión:
do local antigua = impresión -- Almacenar la función de impresión actual como antigua impresión función impresión()s) --[ Función de impresión redefinida. La función de impresión habitual todavía se puede utilizar a través de la vieja huella. El nuevo solo tiene un argumento.]] antigua()s == "foo" y "bar" o s) finalfinal
Cualquier llamada futura a print
ahora se enrutará a través de la nueva función y, debido al alcance léxico de Lua, solo se podrá acceder a la función de impresión anterior mediante la nueva impresión modificada.
Lua también admite cierres, como se demuestra a continuación:
función addto()x) -- Devuelve una nueva función que añade x al argumento retorno función()Sí.) [= Cuando nos referimos a la variable x, que está fuera de la corriente y cuya vida sería más corta que la de este anónimo función, Lua crea un cierre.]=] retorno x + Sí. finalfinal4plus = addto()4)impresión()4plus()3) -- Impresión 7-- Esto también se puede lograr llamando a la función de la siguiente manera:impresión()addto()4)3)-[ Esto es porque estamos llamando la función devuelta de 'addto(4)' con el argumento '3' directamente. Esto también ayuda a reducir el costo de los datos y mejorar el rendimiento si se llama iterativamente.]]
Se crea un nuevo cierre para la variable x
cada vez que se llama a addto
, de modo que cada nueva función anónima devuelta siempre accederá a su propia x código > parámetro. El cierre lo gestiona el recolector de basura de Lua, como cualquier otro objeto.
Mesas
Las tablas son las estructuras de datos más importantes (y, por diseño, el único tipo de datos compuesto integrado) en Lua y son la base de todos los tipos creados por los usuarios. Son arreglos asociativos con adición de clave numérica automática y sintaxis especial.
Una tabla es una colección de claves y pares de datos, donde la clave hace referencia a los datos; en otras palabras, es una matriz asociativa heterogénea hash.
Las tablas se crean utilizando la sintaxis del constructor {}
.
a_table = {} -- Crea una nueva mesa vacía
Las tablas siempre se pasan por referencia (ver Llamar compartiendo).
Una clave (índice) puede tener cualquier valor excepto nil
y NaN, incluidas las funciones.
a_table = {}x = 10} -- Crea una nueva tabla, con una asignación de entrada "x" al número 10.impresión()a_table["x"]) -- Imprime el valor asociado con la clave de cadena, en este caso 10.b_table = a_tableb_table["x"] = 20 -- El valor del cuadro se ha cambiado a 20.impresión()b_table["x"]) - Impresos 20.impresión()a_table["x"]) -- También impresiones 20, porque a_table y b_table ambos se refieren a la misma tabla.
Una tabla se usa a menudo como estructura (o registro) usando cadenas como claves. Debido a que dicho uso es muy común, Lua presenta una sintaxis especial para acceder a dichos campos.
punto = {} x = 10, Sí. = 20 } -- Crear nueva tablaimpresión()punto["x"]) -- Imprimir 10impresión()punto.x) -- Tiene exactamente el mismo significado que la línea anterior. La notación de puntos más fácil de leer es sólo azúcar sintáctica.
Al usar una tabla para almacenar funciones relacionadas, puede actuar como un espacio de nombres.
Punto = {}Punto.nuevo = función()x, Sí.) retorno {}x = x, Sí. = Sí.} ["x"] = x, ["y"] = y]finalPunto.set_x = función()punto, x) punto.x = x - punto ["x"] = x;final
A las tablas se les asigna automáticamente una clave numérica, lo que les permite usarse como un tipo de datos de matriz. El primer índice automático es 1 en lugar de 0 como lo es para muchos otros lenguajes de programación (aunque se permite un índice explícito de 0).
Una clave numérica 1
es distinta de una clave de cadena "1"
.
array = {} "a", "b", "c", "d" } - Los índices se asignan automáticamente.impresión()array[2]) -- Impresión "b". La indexación automática en Lua comienza en 1.impresión()#array) -- Impresión 4. # es el operador de longitud para tablas y cuerdas.array[0] = "z" - Cero es un índice legal.impresión()#array) -- Siguen imprimiendo 4, ya que los arrays Lua están basados en 1.
La longitud de una tabla t
se define como cualquier índice entero n
tal que t[n]
no es nil
y t[n+1]
es nil
; además, si t[1]
es nil
, n
puede ser cero. Para una matriz regular, con valores no nulos de 1 a un n
dado, su longitud es exactamente esa n
, el índice de su último valor. Si la matriz tiene "agujeros" (es decir, valores nulos entre otros valores no nulos), entonces #t
puede ser cualquiera de los índices que preceden directamente a un valor nil
(es decir, puede considerar cualquier valor nulo como el final de la matriz).
Ejemplo ={} {}1, 2, 3, 4} {}5, 6, 7, 8}}impresión()Ejemplo[1[ ]3]) -- Impresión "3"impresión()Ejemplo[2[ ]4]) -- Impresión "8"
Una tabla puede ser una matriz de objetos.
función Punto()x, Sí.) -- "Point" objeto constructor retorno {} x = x, Sí. = Sí. } -- Crea y devuelve un nuevo objeto (tabla)finalarray = {} Punto()10, 20), Punto()30, 40), Punto()50, 60) } -- Crea una variedad de puntos -- array = { x = 10, y = 20 }, { x = 30, y = 40 }, { x = 50, y = 60 };impresión()array[2].Sí.) -- Imprimir 40
Usar un mapa hash para emular una matriz normalmente es más lento que usar una matriz real; sin embargo, las tablas de Lua están optimizadas para usarse como matrices para ayudar a evitar este problema.
Metatablas
La semántica extensible es una característica clave de Lua, y el concepto de metatabla permite una potente personalización de las tablas. El siguiente ejemplo muestra un "infinito" mesa. Para cualquier n
, fibs[n]
dará el n
-ésimo número de Fibonacci usando programación dinámica y memorización.
fibs = {} 1, 1 } -- Valores iniciales para fibs[1] y fibs[2].setmetatable()fibs, {} __index = función()valores, n) --[__index es una función predefinida por Lua, se llama si la clave "n" no existe.]] valores[n] = valores[n - 1] + valores[n - 2] -- Calcular y memoizar fibs[n]. retorno valores[n] final})
Programación orientada a objetos
Aunque Lua no tiene un concepto integrado de clases, la programación orientada a objetos se puede emular usando funciones y tablas. Un objeto se forma poniendo métodos y campos en una tabla. La herencia (tanto única como múltiple) se puede implementar con metatablas, delegando métodos y campos inexistentes a un objeto principal.
No existe el concepto de "clase" con estas técnicas; más bien, se utilizan prototipos, similares a Self o JavaScript. Los nuevos objetos se crean con un método de fábrica (que construye nuevos objetos desde cero) o mediante la clonación de un objeto existente.
Crear un objeto vectorial básico:
local Vectorial = {}local VectorMeta = {} __index = Vectorial}función Vectorial.nuevo()x, Sí., z) -- El constructor retorno setmetatable({x = x, Sí. = Sí., z = z} VectorMeta)finalfunción Vectorial.magnitud()auto) - Otro método retorno math.sqrt()auto.x^2 + auto.Sí.^2 + auto.z^2)finallocal vec = Vectorial.nuevo()0, 1, 0) -- Crear un vectorimpresión()vec.magnitud()vec) - Llamar un método (salida: 1)impresión()vec.x) -- Accede a una variable miembro (salida: 0)
Aquí, setmetatable< /span>
le dice a Lua que busque un elemento en el Vector
tabla si no está presente en la vec
. vec.magnitud
, que es equivalente a vec["magnitud"]
, primero busca en el vec
tabla para la tabla magnitud
elemento. vec< /code> la tabla no tiene un
magnitude
, pero su metatabla delega al elemento Vector
tabla para magnitud
elemento cuando no se encuentra en el vec
table.
Lua proporciona algo de azúcar sintáctico para facilitar la orientación a objetos. Para declarar funciones miembro dentro de una tabla prototipo, se puede usar función tabla:función< span class="p">(args)
, que es equivalente a función tabla.función(yo, argumentos)< /código>. Los métodos de clase de llamada también utilizan los dos puntos:
objeto:función(args)
es equivalente a objeto.función (objeto, argumentos)
.
Teniendo eso en cuenta, aquí hay una clase correspondiente con :
azúcar sintáctico:
local Vectorial = {}Vectorial.__index = Vectorialfunción Vectorial:nuevo()x, Sí., z) -- El constructor -- Puesto que la definición de función utiliza un colon, -- su primer argumento es "self" que se refiere - a "Vector" retorno setmetatable({x = x, Sí. = Sí., z = z} auto)finalfunción Vectorial:magnitud() - Otro método -- Referencia del objeto implícito usando uno mismo retorno math.sqrt()auto.x^2 + auto.Sí.^2 + auto.z^2)finallocal vec = Vectorial:nuevo()0, 1, 0) -- Crear un vectorimpresión()vec:magnitud()) - Llamar un método (salida: 1)impresión()vec.x) -- Accede a una variable miembro (salida: 0)
Herencia
Lua admite el uso de metatablas para dar herencia de clase a Lua. En este ejemplo, permitimos que los vectores tengan sus valores multiplicados por una constante en una clase derivada.
local Vectorial = {}Vectorial.__index = Vectorialfunción Vectorial:nuevo()x, Sí., z) -- El constructor -- Aquí, el yo se refiere a cualquier clase "nueva" - método que llamamos. En una clase derivada, el ego -- ser la clase derivada; en la clase Vector, auto - será Vector retorno setmetatable({x = x, Sí. = Sí., z = z} auto)finalfunción Vectorial:magnitud() - Otro método -- Referencia del objeto implícito usando uno mismo retorno math.sqrt()auto.x^2 + auto.Sí.^2 + auto.z^2)final-- Ejemplo de herencia de claselocal VectorMult = {}VectorMult.__index = VectorMultsetmetatable()VectorMult, Vectorial) -- Make Vector Mult a child of Vectorfunción VectorMult:multiplica multiplica multiplica multiplica multiplica multiplica()valor) auto.x = auto.x * valor auto.Sí. = auto.Sí. * valor auto.z = auto.z * valor retorno autofinallocal vec = VectorMult:nuevo()0, 1, 0) -- Crear un vectorimpresión()vec:magnitud()) - Llamar un método (salida: 1)impresión()vec.Sí.) -- Accede a una variable miembro (salida: 1)vec:multiplica multiplica multiplica multiplica multiplica multiplica()2) -- Multiplicar todos los componentes del vector por 2impresión()vec.Sí.) - Miembro de acceso de nuevo (salida: 2)
Lua también admite la herencia múltiple; __index
puede ser una función o una tabla. También se puede realizar la sobrecarga de operadores; Las metatablas de Lua pueden tener elementos como __add
, __sub
, y así sucesivamente.
Implementación
Los programas de Lua no se interpretan directamente desde el archivo de texto de Lua, sino que se compilan en un código de bytes, que luego se ejecuta en la máquina virtual de Lua. El proceso de compilación suele ser invisible para el usuario y se realiza durante el tiempo de ejecución, especialmente cuando se usa un compilador JIT, pero se puede realizar fuera de línea para aumentar el rendimiento de carga o reducir la huella de memoria del entorno host al omitir el compilador. El código de bytes de Lua también se puede producir y ejecutar desde dentro de Lua, utilizando la función dump
de la biblioteca de cadenas y las funciones load/loadstring/loadfile
. La versión 5.3.4 de Lua está implementada en aproximadamente 24 000 líneas de código C.
Al igual que la mayoría de las CPU, y a diferencia de la mayoría de las máquinas virtuales (que se basan en pilas), la máquina virtual Lua se basa en registros y, por lo tanto, se asemeja más a un diseño de hardware real. La arquitectura de registro evita la copia excesiva de valores y reduce el número total de instrucciones por función. La máquina virtual de Lua 5 es una de las primeras máquinas virtuales puras basadas en registros que tiene un amplio uso. Parrot y Dalvik de Android son otras dos máquinas virtuales basadas en registros muy conocidas. La máquina virtual de PCScheme también estaba basada en registros.
Este ejemplo es la lista de código de bytes de la función factorial definida anteriormente (como se muestra en el compilador luac
5.1):
función יfactorial.lua:1,7 hilo (9 instrucciones, 36 bytes al 0x8063c60) 1 param, 6 ranuras, 0 subvalues, 6 locales, 2 constantes, 0 funciones 1 [2] LOADK 1 -1; 1 2 [3] LOADK 2 -2; 2 3 [3] MOVE 3 0 4 [3] LOADK 4 -1; 1 5 [3] FORPREP 2 1; a 7 6 [4] MUL 1 1 5 7 [3] FORLOOP 2 -2; a 6 8 [6] RETURN 1 2 9 [7] RETURN 0 1
API C
Lua está diseñado para integrarse en otras aplicaciones y proporciona una API C para este propósito. La API se divide en dos partes: el núcleo de Lua y la biblioteca auxiliar de Lua. El diseño de la API de Lua elimina la necesidad de una gestión manual de referencias en el código C, a diferencia de la API de Python. La API, como el lenguaje, es minimalista. La biblioteca auxiliar proporciona una funcionalidad avanzada, que consiste en gran parte en macros de preprocesador que ayudan con operaciones de tablas complejas.
La API de Lua C está basada en pilas. Lua proporciona funciones para empujar y extraer los tipos de datos C más simples (enteros, flotantes, etc.) hacia y desde la pila, así como funciones para manipular tablas a través de la pila. La pila Lua es algo diferente de una pila tradicional; la pila se puede indexar directamente, por ejemplo. Los índices negativos indican compensaciones desde la parte superior de la pila. Por ejemplo, −1 es la parte superior (valor introducido más recientemente), mientras que los índices positivos indican compensaciones desde la parte inferior (valor más antiguo). La clasificación de datos entre las funciones C y Lua también se realiza mediante la pila. Para llamar a una función Lua, los argumentos se colocan en la pila y luego se usa lua_call
para llamar a la función real. Al escribir una función C para llamarla directamente desde Lua, los argumentos se leen de la pila.
Aquí hay un ejemplo de cómo llamar a una función Lua desde C:
#include Identificado.h#include ■lua.h // Biblioteca principal de Lua (lua_*)#include - No. // Lua auxiliary library (luaL_*)int principal()vacío){} // crear un estado de Lua lua_State *L = luaL_newstate(); // cargar y ejecutar una cadena si ()luaL_dostring()L, "función foo (x,y) retorno x+y extremo") {} lua_close()L); retorno -1; } // valor impulsor de "foo" global (la función definida arriba) // a la pila, seguido de enteros 5 y 3 lua_getglobal()L, "foo"); lua_pushinteger()L, 5); lua_pushinteger()L, 3); lua_call()L, 2, 1); // llamar a una función con dos argumentos y un valor de retorno printf()Resultado: %dn", lua_tointeger()L, -1)); // Impresión del valor entero del artículo en la parte superior de la pila lua_pop()L, 1); // volver pila al estado original lua_close()L); // close Lua state retorno 0;}
Ejecutar este ejemplo da:
$ cc -o ejemplo ejemplo.c -llua $./ejemplo Resultado: 8
La API de C también proporciona algunas tablas especiales, ubicadas en varios "pseudoíndices" en la pila de Lua. En LUA_GLOBALSINDEX
anterior a Lua 5.2 se encuentra la tabla global, _G
desde dentro de Lua, que es el espacio de nombres principal. También hay un registro ubicado en LUA_REGISTRYINDEX
donde los programas C pueden almacenar valores de Lua para su posterior recuperación.
Módulos
Además de los módulos de biblioteca estándar (núcleo), es posible escribir extensiones utilizando la API de Lua. Los módulos de extensión son objetos compartidos que se pueden utilizar para ampliar la funcionalidad del intérprete proporcionando funciones nativas a los scripts de Lua. Los scripts de Lua pueden cargar módulos de extensión utilizando require
, al igual que los módulos escritos en el mismo Lua, o con package.loadlib
. Cuando se carga una biblioteca de C a través de require("foo")
, Lua buscará la función luaopen_foo
y la llamará, que actúa como cualquier función de C a la que se pueda llamar. de Lua y generalmente devuelve una tabla llena de métodos. Una creciente colección de módulos conocida como rocks está disponible a través de un sistema de administración de paquetes llamado LuaRocks, en el espíritu de CPAN, RubyGems y Python egg. Existen enlaces Lua preescritos para los lenguajes de programación más populares, incluidos otros lenguajes de secuencias de comandos. Para C++, hay una serie de enfoques basados en plantillas y algunos generadores de enlaces automáticos.
Aplicaciones
En el desarrollo de videojuegos, los programadores utilizan ampliamente Lua como lenguaje de secuencias de comandos, principalmente debido a su facilidad de integración percibida, ejecución rápida y curva de aprendizaje corta. Los juegos notables que usan Lua incluyen Roblox, Garry's Mod, World of Warcraft, Payday 2, Phantasy Star Online 2, Dota 2, Crysis y muchos otros. Algunos juegos que no son compatibles de forma nativa con la programación o secuencias de comandos de Lua tienen esta funcionalidad añadida por mods, como lo hace ComputerCraft para Minecraft. Además, Lua también se usa en software que no es de videojuegos, como Adobe Lightroom, Moho, iClone, Aerospike y cierto software de sistema en FreeBSD y NetBSD, y se usa como lenguaje de secuencias de comandos de plantilla en MediaWiki usando la extensión Scribunto.
En 2003, una encuesta realizada por GameDev.net mostró que Lua era el lenguaje de secuencias de comandos más popular para la programación de juegos. El 12 de enero de 2012, Lua fue anunciada como ganadora del premio Front Line Award 2011 de la revista Game Developer en la categoría Herramientas de programación.
Una gran cantidad de aplicaciones que no son de juegos también usan Lua para la extensibilidad, como LuaTeX, una implementación del lenguaje de configuración de tipos TeX, Redis, una base de datos de valores clave, Neovim, un editor de texto, Nginx, un servidor web. y Wireshark, un analizador de paquetes de red.
A través de la extensión Scribunto, Lua está disponible como un lenguaje de secuencias de comandos del lado del servidor en el software MediaWiki que impulsa Wikipedia y otros wikis. Entre sus usos se encuentran permitir la integración de datos de Wikidata en artículos y potenciar el sistema taxobox automatizado.
Idiomas derivados
Idiomas que compilan a Lua
- MoonScript es un lenguaje de scripting dinámico y sensible al espacio blanco inspirado en CoffeeScript, que se compila en Lua. Esto significa que en lugar de usar
do
yend
(o{
y}
) para delimitar secciones de código que utiliza las roturas de línea y estilo de indentación. Un uso notable de MoonScript es el sitio web de distribución de videojuegos Itch.io. - Haxe apoya la compilación a un objetivo Lua, apoyando Lua 5.1-5.3, así como LuaJIT 2.0 y 2.1.
- Fennel, un dialecto de Lisp que apunta a Lua.
- Urn, un dialecto Lisp que se construye en Lua.
- Amulet, un lenguaje funcional tipo ML, cuyo compilador produce archivos Lua.
Dialectos
- LuaJIT
- Luau de Roblox, Lua 5.1 idioma con escritura gradual y adiciones ergonómicas.
- Ravi, JIT-enabled Lua 5.3 idioma con escritura estática opcional. JIT se guía por información de tipo.
- Shine, un tenedor de LuaJIT con muchas extensiones, incluyendo un sistema de módulos y un sistema macro.
- Glua, una versión modificada incrustada en el juego Garrys Mod como su lenguaje de scripting.
Además, la comunidad de usuarios de Lua proporciona algunos parches potentes además de la implementación de C de referencia.
Contenido relacionado
Extensión de nombre de archivo
Eiffel (lenguaje de programación)
CD-i