Looking for lua Answers? Try Ask4KnowledgeBase
Looking for lua Keywords? Try Ask4Keywords

LuaEmpezando con Lua


Observaciones

Logo de lua

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

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éricos for bucles.

hacer bloques

local a = 10
do
    print(a) --> 10
    local a = 20
    print(a) --> 20
end
print(a) --> 10
 

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.

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.

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.