Lua Tutorial
Empezando con Lua
Buscar..
Observaciones
Lua es un lenguaje de scripting minimalista, liviano e integrable. Está siendo diseñado, implementado y mantenido por un equipo de la PUC-Rio , la Pontificia Universidad Católica de Río de Janeiro en Brasil. La lista de correo está abierta para involucrarse.
Los casos de uso comunes para Lua incluyen scripts de videojuegos, extensión de aplicaciones con complementos y configuraciones, envolviendo un poco de lógica empresarial de alto nivel o simplemente incorporándolos en dispositivos como televisores, automóviles, etc.
Para las tareas de alto rendimiento, hay una implementación independiente utilizando el compilador Just -in-time disponible llamado LuaJIT .
Versiones
Versión | Notas | Fecha de lanzamiento |
---|---|---|
1.0 | Lanzamiento inicial, no público. | 1993-07-28 |
1.1 | Primer lanzamiento público. Documento de conferencia describiéndolo. | 1994-07-08 |
2.1 | A partir de Lua 2.1, Lua estuvo disponible de forma gratuita para todos los fines, incluidos los usos comerciales. Diario que lo describe. | 1995-02-07 |
2.2 | Cadenas largas, la interfaz de depuración, mejores seguimientos de pila | 1995-11-28 |
2.4 | Compilador luac externo | 1996-05-14 |
2.5 | Patrón de coincidencia y funciones vararg. | 1996-11-19 |
3.0 | Se introdujo auxlib, una biblioteca para ayudar a escribir bibliotecas Lua | 1997-07-01 |
3.1 | Funciones anónimas y cierres de funciones mediante "upvalues". | 1998-07-11 |
3.2 | Biblioteca de depuración y nuevas funciones de tabla. | 1999-07-08 |
3.2.2 | 2000-02-22 | |
4.0 | Múltiples estados, declaraciones "for", renovación de API. | 2000-11-06 |
4.0.1 | 2002-07-04 | |
5.0 | Coroutines, metatables, alcance léxico completo, llamadas de cola, booleanos pasan a licencia MIT. | 2003-04-11 |
5.0.3 | 2006-06-26 | |
5.1 | Renovación del sistema de módulos, recolector de basura incremental, metatables para todos los tipos, actualización de luaconf.h, analizador completamente reentrante, argumentos variadic. | 2006-02-21 |
5.1.5 | 2012-02-17 | |
5.2 | Colector de basura de emergencia, goto, finalizadores para mesas. | 2011-12-16 |
5.2.4 | 2015-03-07 | |
5.3 | Compatibilidad básica con UTF-8, operaciones bitwise, enteros de 32 / 64bit. | 2015-01-12 |
5.3.4 | Ultima versión. | 2017-01-12 |
Instalación
Binarios
Los binarios de Lua son proporcionados por la mayoría de las distribuciones de GNU / Linux como un paquete.
Por ejemplo, en Debian, Ubuntu y sus derivados se pueden adquirir ejecutando esto:
sudo apt-get install lua50
sudo apt-get install lua51
sudo apt-get install lua52
Hay algunas compilaciones semi oficiales proporcionadas para Windows, MacOS y algunos otros sistemas operativos alojados en SourceForge .
Los usuarios de Apple también pueden instalar Lua fácilmente usando Homebrew :
brew install lua
(Actualmente Homebrew tiene 5.2.4, para 5.3 ver Homebrew / versiones ).
Fuente
La fuente está disponible en la página oficial . La adquisición de fuentes y la construcción en sí debe ser trivial. En sistemas Linux lo siguiente debería ser suficiente:
$ wget http://lua.org/ftp/lua-5.3.3.tar.gz
$ echo "a0341bc3d1415b814cc738b2ec01ae56045d64ef ./lua-5.3.3.tar.gz" | sha1sum -c -
$ tar -xvf ./lua-5.3.3.tar.gz
$ make -C ./lua-5.3.3/ linux
En el ejemplo anterior, básicamente estamos descargando un tarball
fuente desde el sitio oficial, verificando su suma de comprobación y extrayendo y ejecutando make
. (Revise la suma de verificación en la página oficial ).
Nota: debe especificar qué objetivo de compilación desea. En el ejemplo, especificamos linux
. Otros objetivos de compilación disponibles incluyen solaris
, aix
, bsd
, freebsd
, macosx
, mingw
, etc. Consulte doc/readme.html
, que se incluye en la fuente, para obtener más detalles. (También puede encontrar la última versión de README en línea ).
Módulos
Las bibliotecas estándar están limitadas a primitivas:
-
coroutine
- funcionalidad de gestión de coroutine -
debug
- debug hooks y herramientas -
io
- primitivas básicas de IO -
package
- funcionalidad de gestión de módulos -
string
- string y funcionalidad de coincidencia de patrones específicos de Lua -
table
- primitivas para tratar con un tipo Lua esencial pero complejo - tablas -
os
- operaciones básicas del sistema operativo -
utf8
-utf8
básicas de UTF-8 (desde Lua 5.3)
Todas estas bibliotecas pueden deshabilitarse para una compilación específica o cargarse en tiempo de ejecución.
Las bibliotecas y la infraestructura de Lua de terceros para distribuir módulos son escasas, pero están mejorando. Proyectos como LuaRocks , Lua Toolbox y LuaDist están mejorando la situación. Se puede encontrar mucha información y muchas sugerencias en el antiguo Wiki de Lua , pero tenga en cuenta que parte de esta información es bastante antigua y está desactualizada.
Comentarios
Los comentarios de una sola línea en Lua comienzan con --
y continúan hasta el final de la línea:
-- this is single line comment
-- need another line
-- huh?
Los comentarios del bloque comienzan con --[[
y terminan con ]]
:
--[[
This is block comment.
So, it can go on...
and on...
and on....
]]
Los comentarios de bloque utilizan el mismo estilo de delimitadores que las cadenas largas; se puede agregar cualquier número de signos iguales entre los paréntesis para delimitar un comentario:
--[=[
This is also a block comment
We can include "]]" inside this comment
--]=]
--[==[
This is also a block comment
We can include "]=]" inside this comment
--]==]
Un buen truco para comentar trozos de código es rodearlo con --[[
y --]]
:
--[[
print'Lua is lovely'
--]]
Para reactivar el fragmento, simplemente añada un -
a la secuencia de apertura de comentarios:
---[[
print'Lua is lovely'
--]]
De esta manera, la secuencia --
en la primera línea comienza un comentario de una sola línea, al igual que la última línea, y la declaración de print
no se comenta.
Yendo un paso más allá, se pueden configurar dos bloques de código de tal manera que si el primer bloque se comenta, el segundo no lo estará, y viceversa:
---[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Para activar el segundo fragmento mientras deshabilita el primer fragmento, elimine el encabezado -
en la primera línea:
--[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Ejecución de programas lua.
Por lo general, Lua se envía con dos binarios:
-
lua
- intérprete independiente y shell interactivo -
luac
- compilador bytecode
Digamos que tenemos un programa de ejemplo ( bottles_of_mate.lua
) como este:
local string = require "string"
function bottle_take(bottles_available)
local count_str = "%d bottles of mate on the wall."
local take_str = "Take one down, pass it around, " .. count_str
local end_str = "Oh noes, " .. count_str
local buy_str = "Get some from the store, " .. count_str
local bottles_left = 0
if bottles_available > 0 then
print(string.format(count_str, bottles_available))
bottles_left = bottles_available - 1
print(string.format(take_str, bottles_left))
else
print(string.format(end_str, bottles_available))
bottles_left = 99
print(string.format(buy_str, bottles_left))
end
return bottles_left
end
local bottle_count = 99
while true do
bottle_count = bottle_take(bottle_count)
end
El programa en sí puede ejecutarse ejecutando lo siguiente en su shell:
$ lua bottles_of_mate.lua
La salida debería verse así, ejecutándose en el bucle sin fin:
Get some from the store, 99 bottles of mate on the wall.
99 bottles of mate on the wall.
Take one down, pass it around, 98 bottles of mate on the wall.
98 bottles of mate on the wall.
Take one down, pass it around, 97 bottles of mate on the wall.
97 bottles of mate on the wall.
...
...
3 bottles of mate on the wall.
Take one down, pass it around, 2 bottles of mate on the wall.
2 bottles of mate on the wall.
Take one down, pass it around, 1 bottles of mate on the wall.
1 bottles of mate on the wall.
Take one down, pass it around, 0 bottles of mate on the wall.
Oh noes, 0 bottles of mate on the wall.
Get some from the store, 99 bottles of mate on the wall.
99 bottles of mate on the wall.
Take one down, pass it around, 98 bottles of mate on the wall.
...
Puedes compilar el programa en el código de bytes de Lua ejecutando lo siguiente en tu shell:
$ luac bottles_of_mate.lua -o bottles_of_mate.luac
También está disponible la lista de bytecode ejecutando lo siguiente:
$ luac -l bottles_of_mate.lua
main <./bottles.lua:0,0> (13 instructions, 52 bytes at 0x101d530)
0+ params, 4 slots, 0 upvalues, 2 locals, 4 constants, 1 function
1 [1] GETGLOBAL 0 -1 ; require
2 [1] LOADK 1 -2 ; "string"
3 [1] CALL 0 2 2
4 [22] CLOSURE 1 0 ; 0x101d710
5 [22] MOVE 0 0
6 [3] SETGLOBAL 1 -3 ; bottle_take
7 [24] LOADK 1 -4 ; 99
8 [27] GETGLOBAL 2 -3 ; bottle_take
9 [27] MOVE 3 1
10 [27] CALL 2 2 2
11 [27] MOVE 1 2
12 [27] JMP -5 ; to 8
13 [28] RETURN 0 1
function <./bottles.lua:3,22> (46 instructions, 184 bytes at 0x101d710)
1 param, 10 slots, 1 upvalue, 6 locals, 9 constants, 0 functions
1 [5] LOADK 1 -1 ; "%d bottles of mate on the wall."
2 [6] LOADK 2 -2 ; "Take one down, pass it around, "
3 [6] MOVE 3 1
4 [6] CONCAT 2 2 3
5 [7] LOADK 3 -3 ; "Oh noes, "
6 [7] MOVE 4 1
7 [7] CONCAT 3 3 4
8 [8] LOADK 4 -4 ; "Get some from the store, "
9 [8] MOVE 5 1
10 [8] CONCAT 4 4 5
11 [9] LOADK 5 -5 ; 0
12 [11] EQ 1 0 -5 ; - 0
13 [11] JMP 16 ; to 30
14 [12] GETGLOBAL 6 -6 ; print
15 [12] GETUPVAL 7 0 ; string
16 [12] GETTABLE 7 7 -7 ; "format"
17 [12] MOVE 8 1
18 [12] MOVE 9 0
19 [12] CALL 7 3 0
20 [12] CALL 6 0 1
21 [13] SUB 5 0 -8 ; - 1
22 [14] GETGLOBAL 6 -6 ; print
23 [14] GETUPVAL 7 0 ; string
24 [14] GETTABLE 7 7 -7 ; "format"
25 [14] MOVE 8 2
26 [14] MOVE 9 5
27 [14] CALL 7 3 0
28 [14] CALL 6 0 1
29 [14] JMP 15 ; to 45
30 [16] GETGLOBAL 6 -6 ; print
31 [16] GETUPVAL 7 0 ; string
32 [16] GETTABLE 7 7 -7 ; "format"
33 [16] MOVE 8 3
34 [16] MOVE 9 0
35 [16] CALL 7 3 0
36 [16] CALL 6 0 1
37 [17] LOADK 5 -9 ; 99
38 [18] GETGLOBAL 6 -6 ; print
39 [18] GETUPVAL 7 0 ; string
40 [18] GETTABLE 7 7 -7 ; "format"
41 [18] MOVE 8 4
42 [18] MOVE 9 5
43 [18] CALL 7 3 0
44 [18] CALL 6 0 1
45 [21] RETURN 5 2
46 [22] RETURN 0 1
Empezando
variables
var = 50 -- a global variable
print(var) --> 50
do
local var = 100 -- a local variable
print(var) --> 100
end
print(var) --> 50
-- The global var (50) still exists
-- The local var (100) has gone out of scope and can't be accessed any longer.
tipos
num = 20 -- a number
num = 20.001 -- still a number
str = "zaldrizes buzdari iksos daor" -- a string
tab = {1, 2, 3} -- a table (these have their own category)
bool = true -- a boolean value
bool = false -- the only other boolean value
print(type(num)) --> 'number'
print(type(str)) --> 'string'
print(type(bool)) --> 'boolean'
type(type(num)) --> 'string'
-- Functions are a type too, and first-class values in Lua.
print(type(print)) --> prints 'function'
old_print = print
print = function (x) old_print "I'm ignoring the param you passed me!" end
old_print(type(print)) --> Still prints 'function' since it's still a function.
-- But we've (unhelpfully) redefined the behavior of print.
print("Hello, world!") --> prints "I'm ignoring the param you passed me!"
El tipo especial nil
Otro tipo en Lua es nil
. El único valor en el nil
tipo es nil
. nil
existe para ser diferente de todos los demás valores en Lua. Es un tipo de valor sin valor.
print(foo) -- This prints nil since there's nothing stored in the variable 'foo'.
foo = 20
print(foo) -- Now this prints 20 since we've assigned 'foo' a value of 20.
-- We can also use `nil` to undefine a variable
foo = nil -- Here we set 'foo' to nil so that it can be garbage-collected.
if nil then print "nil" end --> (prints nothing)
-- Only false and nil are considered false; every other value is true.
if 0 then print "0" end --> 0
if "" then print "Empty string!" --> Empty string!
expresiones
a = 3
b = a + 20 a = 2 print(b, a) -- hard to read, can also be written as
b = a + 20; a = 2; print(a, b) -- easier to read, ; are optional though
true and true --> returns true
true and 20 --> 20
false and 20 --> false
false or 20 --> 20
true or 20 --> true
tab or {}
--> returns tab if it is defined
--> returns {} if tab is undefined
-- This is useful when we don't know if a variable exists
tab = tab or {} -- tab stays unchanged if it exists; tab becomes {} if it was previously nil.
a, b = 20, 30 -- this also works
a, b = b, a -- switches values
Definiendo funciones
function name(parameter)
return parameter
end
print(name(20)) --> 20
-- see function category for more information
name = function(parameter) return parameter end -- Same as above
booleanos
Solo false
y nil
evalúan como falso, todo lo demás, incluyendo 0
y la cadena vacía evalúan como verdadero.
recolección de basura
tab = {"lots", "of", "data"}
tab = nil; collectgarbage()
-- tab does no longer exist, and doesn't take up memory anymore.
mesas
tab1 = {"a", "b", "c"}
tab2 = tab1
tab2[1] = "d"
print(tab1[1]) --> 'd' -- table values only store references.
--> assigning tables does not copy its content, only the reference.
tab2 = nil; collectgarbage()
print(tab1) --> (prints table address) -- tab1 still exists; it didn't get garbage-collected.
tab1 = nil; collectgarbage()
-- No more references. Now it should actually be gone from memory.
Estos son los conceptos básicos, pero hay una sección sobre tablas con más información.
condiciones
if (condition) then
-- do something
elseif (other_condition) then
-- do something else
else
-- do something
end
para bucles
Hay dos tipos de bucle for
en Lua: un bucle numérico for
bucle y un bucle genérico for
.
Un numérico
for
bucle tiene la siguiente forma:for a=1, 10, 2 do -- for a starting at 1, ending at 10, in steps of 2 print(a) --> 1, 3, 5, 7, 9 end
La tercera expresión en un numérico
for
bucle es el paso por el cual el bucle se incrementará. Esto hace que sea fácil hacer bucles inversos:for a=10, 1, -1 do print(a) --> 10, 9, 8, 7, 6, etc. end
Si se omite la expresión de paso, Lua supone un paso predeterminado de 1.
for a=1, 10 do print(a) --> 1, 2, 3, 4, 5, etc. end
También tenga en cuenta que la variable de bucle es local al bucle
for
. No existirá después de que termine el bucle.
Genérica
for
bucles de trabajo a través de todos los valores que devuelve una función de iterador:for key, value in pairs({"some", "table"}) do print(key, value) --> 1 some --> 2 table end
Lua proporciona varios iteradores integrados (por ejemplo,
pairs
,ipairs
), y los usuarios pueden definir sus propios iteradores personalizados para usarlos con genéricosfor
bucles.
hacer bloques
local a = 10
do
print(a) --> 10
local a = 20
print(a) --> 20
end
print(a) --> 10
Algunas cosas complicadas
A veces, Lua no se comporta como uno pensaría después de leer la documentación. Algunos de estos casos son:
Nil y Nothing no son lo mismo (Common PITFALL!)
Como se esperaba, table.insert(my_table, 20)
agrega el valor 20
a la tabla, y table.insert(my_table, 5, 20)
agrega el valor 20 en la 5ª posición. ¿Qué hace, table.insert(my_table, 5, nil)
embargo, table.insert(my_table, 5, nil)
? Uno podría esperar que trate a nil
como ningún argumento en absoluto, e inserte el valor 5
al final de la tabla, pero en realidad agrega el valor nil
en la quinta posición de la tabla. ¿Cuándo es esto un problema?
(function(tab, value, position)
table.insert(tab, position or value, position and value)
end)({}, 20)
-- This ends up calling table.insert({}, 20, nil)
-- and this doesn't do what it should (insert 20 at the end)
Algo similar sucede con tostring()
:
print (tostring(nil)) -- this prints "nil"
table.insert({}, 20) -- this returns nothing
-- (not nil, but actually nothing (yes, I know, in lua those two SHOULD
-- be the same thing, but they aren't))
-- wrong:
print (tostring( table.insert({}, 20) ))
-- throws error because nothing ~= nil
--right:
local _tmp = table.insert({}, 20) -- after this _tmp contains nil
print(tostring(_tmp)) -- prints "nil" because suddenly nothing == nil
Esto también puede dar lugar a errores al utilizar un código de terceros. Si, por ejemplo, la documentación de algunos estados de función "devuelve donas si tiene suerte, nula", la implementación podría ser algo así.
function func(lucky)
if lucky then
return "donuts"
end
end
esta implementación puede parecer razonable al principio; devuelve donas cuando tiene que hacerlo, y cuando escribe result = func(false)
resultado contendrá el valor nil
.
Sin embargo, si se escribiera print(tostring(func(false)))
lua arrojaría un error que se parece a este stdin:1: bad argument #1 to 'tostring' (value expected)
¿Porqué es eso? tostring
claramente obtiene una discusión, aunque sea nil
. Incorrecto. func no devuelve nada en absoluto, por lo que tostring(func(false))
es lo mismo que tostring()
y NO lo mismo que tostring(nil)
.
Los errores que dicen "valor esperado" son una clara indicación de que esta podría ser la fuente del problema.
Dejando huecos en matrices
Este es un gran escollo si eres nuevo en lua, y hay mucha información en la categoría de tablas.
Hola Mundo
Este es el código hola mundo:
print("Hello World!")
¿Cómo funciona? ¡Es sencillo! Lua ejecuta print()
función print()
y usa "Hello World"
cadena "Hello World"
como argumento.