Lua ( / ˈl uː ə / 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. [3] Lua es un software multiplataforma , ya que el intérprete del bytecode compilado está escrito en ANSI C , [4] y Lua tiene una interfaz de programación de aplicaciones ( API ) C relativamente simple para integrarlo en aplicaciones. [5]
Lua se originó en 1993 como un lenguaje para extender aplicaciones de software y satisfacer la creciente demanda de personalización de la época. Proveía las funciones básicas de la mayoría de los lenguajes de programación procedimental , pero no incluía características más complicadas o específicas del dominio ; en cambio, incluía mecanismos para extender el lenguaje, lo que permitía a los programadores implementar dichas características. Como Lua estaba destinado a ser un lenguaje de extensión integrable general, los diseñadores de Lua se enfocaron en mejorar su velocidad , portabilidad , extensibilidad y facilidad de uso en el desarrollo.
Lua fue creada en 1993 por Roberto Ierusalimschy , Luiz Henrique de Figueiredo y Waldemar Celes, miembros del Grupo de Tecnología Gráfica Computacional (Tecgraf) de la Pontificia Universidad Católica de Río de Janeiro , en Brasil .
Desde 1977 hasta 1992, Brasil mantuvo una política de fuertes barreras comerciales (denominada reserva de mercado) para hardware y software de computadoras , creyendo que Brasil podía y debía producir su propio hardware y software. En ese clima, los clientes de Tecgraf no podían permitirse, ni política ni financieramente, comprar software personalizado del exterior; bajo la reserva de mercado, los clientes tendrían que pasar por un complejo proceso burocrático para demostrar que sus necesidades no podían ser satisfechas por empresas brasileñas. Esas razones llevaron a Tecgraf a implementar las herramientas básicas que necesitaba desde cero. [6]
Los predecesores de Lua fueron los lenguajes de descripción/configuración de datos Simple Object Language (SOL) y el lenguaje de entrada de datos (DEL). [7] Se habían desarrollado de forma independiente en Tecgraf en 1992-1993 para añadir algo de 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 creciente necesidad de añadirles potencia de programación completa.
En La evolución de Lua , los autores del lenguaje escribieron: [6]
En 1993, el único contendiente real era Tcl , que había sido diseñado explícitamente para ser integrado en aplicaciones. Sin embargo, Tcl tenía una sintaxis desconocida, no ofrecía un buen soporte para la descripción de datos y solo se ejecutaba en plataformas Unix. No consideramos LISP ni Scheme debido a su sintaxis poco amigable. Python todavía estaba en su infancia. En la atmósfera libre y de "hazlo tú mismo" que reinaba entonces en Tecgraf, era bastante natural que intentáramos desarrollar nuestro propio lenguaje de scripting... Debido a que muchos usuarios potenciales del lenguaje no eran programadores profesionales, el lenguaje debía evitar la sintaxis y la semántica crípticas. La implementación del nuevo lenguaje debía ser altamente portable, porque los clientes de Tecgraf tenían una colección muy diversa de plataformas informáticas. Finalmente, dado que esperábamos que otros productos de Tecgraf también necesitaran integrar un lenguaje de scripting, el nuevo lenguaje debía seguir el ejemplo de SOL y proporcionarse como una biblioteca con una API de C.
Lua 1.0 fue diseñado de tal manera que sus constructores de objetos, siendo entonces ligeramente diferentes del estilo ligero y flexible actual, incorporaron la sintaxis de descripción de datos de SOL (de ahí el nombre Lua: Sol significa "Sol" en portugués, y Lua significa "Luna"). La sintaxis de Lua para las estructuras de control fue tomada prestada principalmente de Modula ( if
, while
, repeat
/ until
), pero también había tomado influencia de CLU (múltiples asignaciones y múltiples retornos de llamadas de función, 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" [6] ), 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 mecanismo de estructura de datos único y ubicuo (la lista ) fueron una influencia importante en su decisión de desarrollar la tabla como la estructura de datos principal de Lua. [8]
La semántica de Lua ha sido influenciada cada vez más por Scheme con el paso del tiempo, [6] 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 bajo una licencia similar a la licencia BSD . A partir de la versión 5.0, Lua se ha licenciado bajo la licencia MIT . Ambas son licencias de software libre permisivas y son casi idénticas.
Lua se describe comúnmente como un lenguaje " multiparadigma ", que proporciona 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 de grano fino para hacer cumplir el principio del mínimo privilegio .
En general, Lua se esfuerza por proporcionar metacaracterísticas simples y flexibles que se puedan ampliar según sea necesario, en lugar de proporcionar un conjunto de características específicas para un paradigma de programación. Como resultado, el lenguaje base es ligero ; el intérprete de referencia completo solo pesa unos 247 kB compilados [4] y se adapta fácilmente a una amplia gama de aplicaciones.
Como lenguaje de tipado dinámico pensado para su uso como lenguaje de extensión o lenguaje de script , Lua es lo suficientemente compacto como para adaptarse a una variedad de plataformas de host. Admite solo una pequeña cantidad de estructuras de datos atómicas, como valores booleanos , números ( coma flotante de doble precisión y enteros de 64 bits de manera predeterminada) y cadenas . Las estructuras de datos típicas, como matrices , conjuntos , listas y registros, se pueden representar utilizando la única estructura de datos nativa de Lua, la tabla, que es esencialmente una matriz asociativa heterogénea .
Lua implementa un pequeño conjunto de características avanzadas , tales como funciones de primera clase , recolección de basura , cierres , llamadas de cola adecuadas , coerción (conversión automática entre valores de cadena y números en tiempo de ejecución), corrutinas (multitarea cooperativa) y carga dinámica de módulos .
El clásico programa "¡Hola, mundo!" se puede escribir de la siguiente manera, con o sin paréntesis: [9] [a]
imprimir ( "¡Hola, mundo!" )
imprimir "¡Hola, mundo!"
Un comentario en Lua comienza con un doble guion y se extiende hasta el final de la línea, de forma similar a Ada , Eiffel , Haskell , SQL y VHDL . Las cadenas de varias líneas y los comentarios se marcan con corchetes dobles.
--Comentario de una sola línea --[[ Comentario de varias líneas-- ]]
La función factorial se implementa en este ejemplo:
función factorial ( n ) local x = 1 para i = 2 , n hacer x = x * i fin devolver x fin
Lua tiene un tipo de prueba condicional : if then end
con construcciones opcionales else
y elseif then
de control de ejecución.
La if then end
declaración genérica requiere las tres palabras clave:
Si la condición es entonces --cuerpo de la declaración final
La else
palabra clave se puede agregar con un bloque de declaración adjunto para controlar la ejecución cuando la if
condición se evalúa como false
:
si condición entonces --cuerpo de la declaración de lo contrario --cuerpo de la declaración fin
La ejecución también se puede controlar según múltiples condiciones utilizando las elseif then
palabras clave:
si condición entonces --cuerpo de la declaración elsesi condición entonces --cuerpo de la declaración else --opcional --opcional predeterminado cuerpo de la declaración fin
Lua tiene cuatro tipos de bucles condicionales: el while
bucle , el repeat
bucle (similar a un do while
bucle ), el for
bucle numérico y el bucle genérico for
.
--condición = verdaderomientras la condición haga --declaraciones terminanrepetir --declaraciones hasta que se cumpla la condiciónpara i = primero , último , delta hacer --delta puede ser negativo, lo que permite que el bucle for cuente hacia atrás o hacia arriba --declaraciones --ejemplo: print(i) fin
Este bucle genérico for
iteraría sobre la tabla _G
utilizando la función iteradora estándar pairs
, hasta que retorne nil
:
para clave , valor en pares ( _G ) hacer print ( clave , valor ) fin
Los bucles también se pueden anidar (colocar dentro de otro bucle).
cuadrícula local = { { 11 , 12 , 13 }, { 21 , 22 , 23 }, { 31 , 32 , 33 } }para y , fila en pares ( cuadrícula ) hacer para x , valor en pares ( fila ) hacer imprimir ( x , y , valor ) fin fin
El tratamiento que Lua hace 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 oldprint = print -- Almacena la función de impresión actual como la función oldprint print ( s ) --[[ Redefine la función de impresión. La función de impresión habitual todavía se puede usar a través de oldprint. La nueva tiene solo un argumento.]] oldprint ( s == "foo" y "bar" o s ) end end
Cualquier llamada futura a print
ahora será enrutada a través de la nueva función y, debido al alcance léxico de Lua , la antigua función print solo será accesible mediante la nueva función print modificada.
Lua también admite cierres , como se muestra a continuación:
function addto ( x ) - Devuelve una nueva función que agrega x al argumento return function ( y ) -[[Cuando hacemos referencia a la variable x, que está fuera del alcance actual y cuyo tiempo de vida sería más corto que el de esta función anónima, Lua crea un cierre.]] return x + y end end fourplus = addto ( 4 ) print ( fourplus ( 3 )) - Imprime 7--Esto también se puede lograr llamando a la función de la siguiente manera: print ( addto ( 4 )( 3 )) --[[Esto se debe a que estamos llamando a la función devuelta desde 'addto(4)' con el argumento '3' directamente. Esto también ayuda a reducir el costo de datos y mejorar el rendimiento si se llama de forma iterativa.]]
x
Cada vez que se llama a una variable, se crea un nuevo cierre para la misma addto
, de modo que cada nueva función anónima devuelta siempre accederá a su propio x
parámetro. El cierre lo gestiona el recolector de elementos no utilizados de Lua, al igual que cualquier otro objeto.
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 el usuario. Son matrices asociativas con la adición de una clave numérica automática y una sintaxis especial.
Una tabla es un conjunto de pares de claves y datos, donde los datos están referenciados por clave; en otras palabras, es una matriz asociativa heterogénea con algoritmo hash .
Las tablas se crean utilizando la {}
sintaxis del constructor.
a_table = {} – Crea una nueva tabla vacía
Las tablas siempre se pasan por referencia (ver Llamada por uso compartido ).
Una clave (índice) puede ser cualquier valor excepto nil
y NaN , incluidas las funciones.
a_table = { x = 10 } - Crea una nueva tabla, con una entrada que asigna "x" al número 10. print ( a_table [ "x" ]) - Imprime el valor asociado con la clave de cadena, en este caso 10. b_table = a_table b_table [ "x" ] = 20 - El valor en la tabla ha sido cambiado a 20. print ( b_table [ "x" ]) - Imprime 20. print ( a_table [ "x" ]) - También imprime 20, porque a_table y b_table hacen referencia a la misma tabla.
A menudo se utiliza una tabla como estructura (o registro ) mediante el uso de cadenas como claves. Debido a que este uso es muy común, Lua cuenta con una sintaxis especial para acceder a dichos campos. [11]
punto = { x = 10 , y = 20 } - Crea una nueva tabla print ( punto [ "x" ]) - Imprime 10 print ( punto.x ) - Tiene exactamente el mismo significado que la línea anterior. La notación de puntos, más fácil de leer, es simplemente una sintaxis más simple .
Al utilizar una tabla para almacenar funciones relacionadas, puede actuar como un espacio de nombres.
Punto = {}Punto . nuevo = función ( x , y ) return { x = x , y = y } -- return {["x"] = x, ["y"] = y} finPunto . set_x = function ( punto , x ) punto . x = x -- punto["x"] = x; fin
A las tablas se les asigna automáticamente una clave numérica, lo que permite utilizarlas como un tipo de datos de matriz . El primer índice automático es 1 en lugar de 0, como ocurre en 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. print ( array [ 2 ]) - Imprime "b". La indexación automática en Lua comienza en 1. print ( # array ) - Imprime 4. # es el operador de longitud para tablas y cadenas. array [ 0 ] = "z" - Cero es un índice legal. print ( # array ) - Sigue imprimiendo 4, ya que los arrays de Lua están basados en 1.
La longitud de una tabla t
se define como cualquier índice entero n
tal que t[n]
no sea nil
ni t[n+1]
sea nil
; además, si t[1]
es nil
, n
puede ser cero. Para una matriz regular, con valores distintos de nulos desde 1 hasta un determinado n
, su longitud es exactamente esa n
, el índice de su último valor. Si la matriz tiene "huecos" (es decir, valores nulos entre otros valores distintos de nulos), entonces #t
puede ser cualquiera de los índices que preceden directamente a un nil
valor (es decir, puede considerar cualquier valor nulo como el final de la matriz). [12]
ExampleTable = { { 1 , 2 , 3 , 4 }, { 5 , 6 , 7 , 8 } } print ( ExampleTable [ 1 ][ 3 ]) -- Imprime "3" print ( ExampleTable [ 2 ][ 4 ]) -- Imprime "8"
Una tabla puede ser una matriz de objetos.
function Punto ( x , y ) -- Constructor del objeto "Punto" return { x = x , y = y } -- Crea y devuelve un nuevo objeto (tabla) end array = { Punto ( 10,20 ) , Punto ( 30,40 ), Punto ( 50,60 ) } -- Crea una matriz de puntos -- array = { { x = 10 , y = 20 }, { x = 30, y = 40 }, { x = 50, y = 60 } }; print ( array [ 2 ] .y ) -- Imprime 40
El uso de un mapa hash para emular una matriz normalmente es más lento que el uso de una matriz real; sin embargo, las tablas Lua están optimizadas para su uso como matrices para ayudar a evitar este problema. [13]
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 demuestra una tabla "infinita". Para cualquier n
, fibs[n]
dará el n
-ésimo número de Fibonacci mediante programación dinámica y memorización .
fibs = { 1 , 1 } -- Valores iniciales para fibs[1] y fibs[2]. setmetatable ( fibs , { __index = function ( values , n ) --[[__index es una función predefinida por Lua, se llama si la clave "n" no existe.]] values [ n ] = values [ n - 1 ] + values [ n - 2 ] -- Calcular y memorizar fibs[n]. return values [ n ] end })
Aunque Lua no tiene un concepto de clases incorporado , la programación orientada a objetos se puede emular utilizando funciones y tablas. Un objeto se forma colocando métodos y campos en una tabla. La herencia (tanto simple como múltiple) se puede implementar con metatablas, delegando métodos y campos inexistentes a un objeto padre.
Con estas técnicas no existe el concepto de "clase", sino que se utilizan prototipos , similares a Self o JavaScript . Los objetos nuevos se crean con un método de fábrica (que construye objetos nuevos desde cero) o clonando un objeto existente.
Creando un objeto vectorial básico :
Vector local = {} VectorMeta local = { __índice = Vector } función Vector . new ( x , y , z ) -- El constructor retorna setmetatable ({ x = x , y = y , z = z }, VectorMeta ) finfunción Vector .magnitud ( self ) - Otro método return math.sqrt ( self.x ^ 2 + self.y ^ 2 + self.z ^ 2 ) fin local vec = Vector . new ( 0 , 1 , 0 ) -- Crea un vector print ( vec . magnitude ( vec )) -- Llama a un método (salida: 1) print ( vec . x ) -- Accede a una variable miembro (salida: 0)
Aquí, setmetatable
le indica a Lua que busque un elemento en la Vector
tabla si no está presente en vec
ella. , que es equivalente a , primero busca el elemento en la tabla . La tabla no tiene un elemento, pero su metatabla delega a la tabla el elemento cuando no se encuentra en la tabla.vec.magnitude
vec["magnitude"]
vec
magnitude
vec
magnitude
Vector
magnitude
vec
Lua proporciona cierta sintaxis para facilitar la orientación a objetos. Para declarar funciones miembro dentro de una tabla de prototipos, se puede utilizar , que es equivalente a . La llamada a métodos de clase también hace uso de los dos puntos: es equivalente a .function table:func(args)
function table.func(self, args)
object:func(args)
object.func(object, args)
Con esto en mente, aquí hay una clase correspondiente con :
azúcar sintáctica:
Vector local = {} Vector . __índice = Vectorfunción Vector : new ( x , y , z ) -- El constructor -- Dado que la definición de función utiliza dos puntos, -- su primer argumento es "self" que se refiere -- a "Vector" return setmetatable ({ x = x , y = y , z = z }, self ) endfunción Vector : magnitud () - Otro método - Referencia al objeto implícito usando self return math.sqrt ( self.x ^ 2 + self.y ^ 2 + self.z ^ 2 ) fin local vec = Vector : new ( 0 , 1 , 0 ) -- Crea un vector print ( vec : magnitude ()) -- Llama a un método (salida: 1) print ( vec . x ) -- Accede a una variable miembro (salida: 0)
Lua admite el uso de metatablas para otorgar herencia de clases a Lua. [14] En este ejemplo, permitimos que los vectores tengan sus valores multiplicados por una constante en una clase derivada.
Vector local = {} Vector . __índice = Vectorfunción Vector : new ( x , y , z ) -- El constructor -- Aquí, self se refiere al método "nuevo" de cualquier clase que -- llamemos. En una clase derivada, self será la clase derivada; en la clase Vector, self será Vector return setmetatable ({ x = x , y = y , z = z }, self ) endfunción Vector : magnitud () - Otro método - Referencia al objeto implícito usando self return math.sqrt ( self.x ^ 2 + self.y ^ 2 + self.z ^ 2 ) fin -- Ejemplo de herencia de clase local VectorMult = {} VectorMult . __index = VectorMult setmetatable ( VectorMult , Vector ) -- Hacer que VectorMult sea un hijo de Vectorfunción VectorMult : multiplicar ( valor ) self . x = self . x * valor self . y = self . y * valor self . z = self . z * valor return self endlocal vec = VectorMult : new ( 0 , 1 , 0 ) -- Crea un vector print ( vec : magnitude ()) -- Llama a un método (salida: 1) print ( vec . y ) -- Accede a una variable miembro (salida: 1) vec : multiplicar ( 2 ) -- Multiplica todos los componentes del vector por 2 print ( vec . y ) -- Accede al miembro nuevamente (salida: 2)
Lua también admite herencia múltiple ; __index
puede ser una función o una tabla. [15] También se puede realizar una sobrecarga de operadores ; las metatablas de Lua pueden tener elementos como __add
, __sub
y así sucesivamente. [16]
Los programas Lua no se interpretan directamente desde el archivo textual de Lua, sino que se compilan en código de bytes, que luego se ejecuta en la máquina virtual (VM) de Lua. El proceso de compilación normalmente es invisible para el usuario y se realiza durante el tiempo de ejecución , especialmente cuando se utiliza un compilador de compilación justo a tiempo (JIT), pero se puede realizar sin conexión para aumentar el rendimiento de carga o reducir la huella de memoria del entorno host al dejar fuera el compilador. El código de bytes de Lua también se puede producir y ejecutar desde dentro de Lua, utilizando la dump
función de la biblioteca de cadenas y las load/loadstring/loadfile
funciones. La versión 5.3.4 de Lua está implementada en aproximadamente 24.000 líneas de código C. [3] [4]
Al igual que la mayoría de las CPU, y a diferencia de la mayoría de las máquinas virtuales (que están basadas en pila ), la VM de Lua está basada en registros y, por lo tanto, se parece más a la mayoría de los diseños de hardware. La arquitectura de registros evita la copia excesiva de valores y reduce la cantidad total de instrucciones por función. La máquina virtual de Lua 5 es una de las primeras VM puras basadas en registros que tiene un uso amplio. [17] Parrot y Dalvik de Android son otras dos VM basadas en registros bien conocidas. La VM de PCScheme también estaba basada en registros. [18]
Este ejemplo es el listado de bytes de la función factorial definida anteriormente (como lo muestra el luac
compilador 5.1): [19]
función <factorial.lua:1,7> (9 instrucciones, 36 bytes en 0x8063c60)1 parámetro, 6 ranuras, 0 valores ascendentes, 6 variables locales, 2 constantes, 0 funciones1 [2] CARGAR 1 -1 ; 12 [3] CARGA 2 -2 ; 23 [3] MOVER 3 04 [3] CARGA 4 -1 ; 15 [3] FORPREP 2 1 ; a 76 [4] MUL 1 1 57 [3] FORLOOP 2 -2 ; hasta 68 [6] REGRESAR 1 29 [7] RETORNO 0 1
Lua está pensado para ser integrado 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. [20] El diseño de la API de Lua elimina la necesidad de contar referencias manualmente (administrar) en código C, a diferencia de la API de Python . La API, al igual que el lenguaje, es minimalista. Las funciones avanzadas las proporciona la biblioteca auxiliar, que consta principalmente de macros de preprocesador que ayudan con operaciones de tabla complejas.
La API de Lua C se basa en la pila . Lua proporciona funciones para insertar y extraer los tipos de datos más simples de C (enteros, flotantes, etc.) de la pila y funciones para manipular tablas a través de la pila. La pila de Lua es algo diferente de una pila tradicional; la pila se puede indexar directamente, por ejemplo. Los índices negativos indican desplazamientos desde la parte superior de la pila. Por ejemplo, −1 es la parte superior (el valor insertado más recientemente), mientras que los índices positivos indican desplazamientos desde la parte inferior (el valor más antiguo). La ordenación de datos entre funciones de C y Lua también se realiza utilizando la pila. Para llamar a una función de Lua, los argumentos se insertan en la pila y luego se lua_call
utiliza para llamar a la función real. Al escribir una función de C para que se llame directamente desde Lua, los argumentos se leen desde la pila.
A continuación se muestra un ejemplo de cómo llamar a una función Lua desde C:
#include <stdio.h> #include <lua.h> // Biblioteca principal de Lua (lua_*) #include <lauxlib.h> // Biblioteca auxiliar de Lua (luaL_*) int main ( void ) { // crea un estado Lua lua_State * L = luaL_newstate (); // cargar y ejecutar una cadena si ( luaL_dostring ( L , "función foo (x,y) devolver x+y fin" )) { lua_close ( L ); devolver -1 ; } // inserta el valor de "foo" global (la función definida arriba) // en la pila, seguido de los enteros 5 y 3 lua_getglobal ( L , "foo" ); lua_pushinteger ( L , 5 ); lua_pushinteger ( L , 3 ); lua_call ( L , 2 , 1 ); // llama a una función con dos argumentos y un valor de retorno printf ( "Resultado: %d \n " , lua_tointeger ( L , -1 )); // imprime el valor entero del elemento en la parte superior de la pila lua_pop ( L , 1 ); // devuelve la pila al estado original lua_close ( L ); // cierra el estado de Lua return 0 ; }
Al ejecutar este ejemplo se obtiene lo siguiente:
$ 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 la LUA_GLOBALSINDEX
versión anterior a Lua 5.2 [21] se encuentra la tabla globals, _G
de Lua, que es el espacio de nombres principal . También hay un registro ubicado en LUA_REGISTRYINDEX
donde los programas de C pueden almacenar valores de Lua para su posterior recuperación.
Además de los módulos de la 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 las funciones del intérprete proporcionando facilidades nativas a los scripts de Lua. Los scripts de Lua pueden cargar módulos de extensión utilizando require
, [20] al igual que los módulos escritos en Lua mismo, o con package.loadlib
. [22] Cuando se carga una biblioteca C a través de Lua, buscará la función y la llamará, que actúa como cualquier función C invocable desde Lua y generalmente devuelve una tabla llena de métodos. Un conjunto creciente de módulos denominados rocks están disponibles a través de un sistema de gestión de paquetes llamado LuaRocks , [23] en el espíritu de CPAN , RubyGems y Python eggs. Existen enlaces Lua preescritos para los lenguajes de programación más populares, incluidos otros lenguajes de script. [24] Para C++, hay una serie de enfoques basados en plantillas y algunos generadores de enlaces automáticos.require('foo')
luaopen_foo
En el desarrollo de videojuegos , Lua se usa ampliamente como lenguaje de scripting , principalmente debido a su facilidad percibida para incrustar, ejecución rápida y curva de aprendizaje corta . [25] Los juegos notables que usan Lua incluyen Roblox , [26] Garry's Mod , World of Warcraft , Payday 2 , Phantasy Star Online 2 , Dota 2 , Crysis , [27] y muchos otros. Algunos juegos que no admiten de forma nativa la programación o scripting de Lua, tienen esta función agregada por mods, como lo hace ComputerCraft para Minecraft . Además, Lua se usa en software que no es de videojuegos, como Adobe Lightroom , Moho , iClone , Aerospike y algún software de sistema en FreeBSD y NetBSD , y se usa como un lenguaje de scripting de plantilla en MediaWiki usando la extensión Scribunto. [28]
En 2003, una encuesta realizada por GameDev.net mostró que Lua era el lenguaje de programación de juegos más popular. [29] El 12 de enero de 2012, Lua fue anunciado como ganador del premio Front Line Award 2011 de la revista Game Developer en la categoría Herramientas de programación. [30]
Muchas aplicaciones que no son juegos también usan Lua para extensibilidad, como LuaTeX , una implementación del lenguaje de composición tipográfica TeX , Redis , una base de datos clave-valor , ScyllaDB , un almacén de columnas anchas , 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 programación del lado del servidor en el software MediaWiki que ejecuta Wikipedia y otras wikis. [31] Entre sus usos se encuentran permitir la integración de datos de Wikidata en artículos, [32] y potenciar el sistema automatizado taxobox .
do
end
{
}
Además, la comunidad de usuarios de Lua proporciona algunos parches de potencia sobre la implementación de referencia de C. [44]
{{cite book}}
: |work=
ignorado ( ayuda ){{cite web}}
: CS1 maint: bot: estado de URL original desconocido ( enlace )Todo esto nos motivó a comenzar a remodelar Lua 5.1 con el que comenzamos en un nuevo lenguaje derivado que llamamos Luau. Nuestro objetivo es hacer que el lenguaje tenga más rendimiento y más funciones, y facilitar la escritura de código sólido mediante una combinación de linting y verificación de tipos utilizando un sistema de tipos gradual.