Empezando con Lua
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 en bloque comienzan con --[[
y terminan con ]]
:
--[[
This is block comment.
So, it can go on...
and on...
and on....
]]
Los comentarios de bloque usan el mismo estilo de delimitadores que las cadenas largas; Se puede agregar cualquier número de signos de igual entre los corchetes 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 fragmentos de código es rodearlo con --[[
y --]]
:
--[[
print'Lua is lovely'
--]]
Para reactivar el fragmento, simplemente agrega un -
a la secuencia de apertura del comentario:
---[[
print'Lua is lovely'
--]]
De esta forma, la secuencia --
en la primera línea inicia un comentario de una sola línea, al igual que la última línea, y la instrucción 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 está comentado, el segundo no lo estará, y viceversa:
---[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Para activar el segundo fragmento mientras deshabilita el primero, elimine el -
inicial en la primera línea:
--[[
print 'Lua is love'
--[=[]]
print 'Lua is life'
--]=]
Instalación
Binarios
La mayoría de las distribuciones de GNU/Linux proporcionan los binarios de Lua como un paquete.
Por ejemplo, en Debian, Ubuntu y sus derivados se puede adquirir ejecutando esto:
sudo apt-get install lua50
sudo apt-get install lua51
sudo apt-get install lua52
Se proporcionan algunas compilaciones semioficiales 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/versions.)
Fuente
La fuente está disponible en [la página oficial] (https://www.lua.org/download.html). La adquisición de fuentes y la construcción en sí deberían ser triviales. En los 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 del sitio oficial, verificando su suma de verificación y extrayendo y ejecutando make
. (Compruebe dos veces la suma de comprobació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 el código fuente, para obtener más información. detalles. (También puede encontrar la última versión del LÉAME en línea.)
Módulos
Las bibliotecas estándar están limitadas a primitivas:
coroutine
- funcionalidad de gestión de coroutinedebug
- ganchos y herramientas de depuraciónio
- primitivas básicas de E/Spaquete
- funcionalidad de gestión de módulosstring
- funcionalidad de coincidencia de patrones específicos de string y Luatabla
- primitivas para tratar con un tipo Lua esencial pero complejo - tablasos
- operaciones básicas del sistema operativoutf8
- primitivas UTF-8 básicas (desde Lua 5.3)
Todas esas bibliotecas pueden deshabilitarse para una compilación específica o cargarse en tiempo de ejecución.
La infraestructura y las bibliotecas 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 Lua Wiki, pero tenga en cuenta que parte de esta información es bastante antigua y está desactualizada.
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 tipo nil
es nil
. nil
existe para ser diferente de todos los demás valores en Lua. Es una especie 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
Definición de 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 falso
y nil
se evalúan como falsos, todo lo demás, incluidos 0
y la cadena vacía, se evalúan como verdaderos.
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 bucles for
en Lua: un bucle for
numérico y un bucle for
genérico.
-
Un bucle
for
numérico 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
The third expression in a numeric
for
loop is the step by which the loop will increment. This makes it easy to do reverse loops:for a=10, 1, -1 do print(a) --> 10, 9, 8, 7, 6, etc. end
If the step expression is left out, Lua assumes a default step of 1.
for a=1, 10 do print(a) --> 1, 2, 3, 4, 5, etc. end
Also note that the loop variable is local to the
for
loop. It will not exist after the loop is over. -
Los bucles
for
genéricos funcionan a través de todos los valores que devuelve una función iteradora: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 bucles for
genéricos.
hacer bloques
local a = 10
do
print(a) --> 10
local a = 20
print(a) --> 20
end
print(a) --> 10
Algunas cosas difíciles
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 (¡ERROR COMÚN!)
Como era de esperar, 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 quinta posición.
¿Qué hace table.insert(my_table, 5, nil)
? Uno podría esperar que tratara nil
como ningún argumento 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 código de terceros. Si, por ejemplo, la documentación de alguna función dice “devuelve donuts si tiene suerte, nil de lo contrario”, la implementación podría parecerse a esto
function func(lucky)
if lucky then
return "donuts"
end
end
esta implementación puede parecer razonable al principio; devuelve donuts cuando tiene que hacerlo, y cuando escribe result = func(false)
, el 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' (valor esperado)
¿Porqué es eso? tostring
claramente obtiene un argumento, aunque sea nil
. Equivocado. 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 fuerte indicación de que esta podría ser la fuente del problema.
Dejando espacios en las matrices
Esta es una gran trampa si eres nuevo en lua, y hay mucha [información] (https://www.wikiod.com/es/lua/mesas#Evitar espacios en las tablas utilizadas como matrices as-arrays#t=20170113143427074516) en la categoría tables
Ejecutando programas Lua
Por lo general, Lua se envía con dos binarios:
lua
- intérprete independiente y consola interactivaluac
- compilador de código de bytes
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í se puede ejecutar ejecutando lo siguiente en su shell:
$ lua bottles_of_mate.lua
La salida debería verse así, ejecutándose en el ciclo 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.
...
Puede compilar el programa en el código de bytes de Lua ejecutando lo siguiente en su shell:
$ luac bottles_of_mate.lua -o bottles_of_mate.luac
También está disponible la lista de códigos de bytes 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
Hola Mundo
Este es el código de hola mundo:
print("Hello World!")
¿Cómo funciona? ¡Es simple!
Lua ejecuta la función print()
y usa la cadena "Hello World"
como argumento.