Lua es un típico lenguaje de programación procedimental, que ofrece ricas características para el desarrollo. Se trata de un lenguaje potente y sencillo con un enorme conjunto de construcciones significativas.
Al ser un lenguaje orientado a ampliar el software existente, Lua no utiliza el concepto de "programa principal ". Lua funciona dentro del entorno de otros programas, llamados hosts. En este caso GEDKeeper es el host. Un host ejecuta parte del código (siguiente: script) escrito en Lua. Debido a que el host puede extender el potencial de Lua, este último puede resolver una amplia gama de tareas.
Lua es un software de libre distribución, por lo que no ofrece garantías cuando se utiliza de acuerdo con la licencia de Lua. Puede descargar Lua 5.4 en el sitio web oficial de Lua: www.lua.org.
Como muchos otros manuales, éste tiene un estilo formal. Para obtener información técnica detallada sobre el uso del lenguaje debe consultar la documentación en el sitio oficial de Lua. Hay un buen libro sobre Lua, que puede serle útil: se trata de Programming in Lua, ya en su cuarta edicion, de Roberto Ierusalimschy.
Este capítulo describe las construcciones lingüísticas, cómo utilizarlas y qué significan.
Se presentará una interpretación utilizando BNF extendido, donde {a} significa cero o más elementos `a`, y [a] significa un elemento opcional. Se utilza texto normal para los símbolos no terminales, mientras que las palabras clave se resaltan con texto en negrita: palabra clave; todos los demás símbolos terminales se encierran entre comillas simples: '='.
Los nombres (identificadores) en Lua son cadenas de letras, dígitos y caracteres de subrayado. No pueden comenzar con un dígito. Esta es una regla habitual en la mayoría de los lenguajes de programación. Los identificadores se usan para nombrar variables y tablas con valores.
Las siguientes palabras clave están reservadas y no pueden utilizarse como identificadores:
and break do else elseif
end false for function if
in local nil not or
repeat return then true until while
Lua es un lenguaje que distingue entre mayúsculas y minúsculas: `and` es una palabra clave, mientras que `And` y `AND` son dos identificadores válidos diferentes. Existe una convención, que dice que los nombres que comienzan con subrayado y se escriben en mayúsculas (`_VERSION`, por ejemplo), se reservan para nombrar las variables globales internas de Lua.
Estos son otros símbolos permitidos:
+ * / % ^ #
== ~= <= >= < > =
( ) { } [ ]
; : , . .. ...
Los literales de cadena deben ir entre comillas simples o dobles, y pueden contener las siguientes secuencias de escape al estilo del lenguaje de programación C:: '\a' ("campana"), '\b' ("retroceso"), '\f' ("salto de página"), '\n' ("nueva línea"), '\r' ("retorno de carro"), '\t' ("tabulador horizontal"), '\v' ("tabulador vertical"), '\"' ("dobles comillas"), '\'' ("comilla simple"). Cuando necesite añadir un salto de línea en una línea larga de código, también puede utilizar la barra invertida. Para añadir un carácter a una cadena literal mediante un código de caracteres, utilice la siguiente secuencia de escape: \ddd, donde ddd es una secuencia de tres dígitos como máximo. (Cabe señalar que cuando se necesita añadir un dígito después de un carácter escrito por su código, hay que utilizar exactamente tres dígitos en la secuencia de escape). Las cadenas de Lua pueden contener cualquier valor de 8 bytes, incluyendo el carácter nulo, que se escribe como '\0'.
Debes utilizar secuencias de escape cuando necesites añadir un carácter de comillas dobles, un carácter de nueva línea, una barra invertida o un carácter nulo a un literal de cadena. Cualquier otro símbolo puede escribirse tal cual.
Los números pueden escribirse con la parte decimal y el exponente opcionales. Si desea definir un número hexadecimal, utilice el prefijo '0x'. A continuación se muestra un ejemplo de literales numéricos válidos:
3 3.0 3.1416 314.16e-2 0.31416E1 0xff 0x56
Un guión doble ('--'), en cualquier lugar fuera de una cadena literal, inicia un comentario. Cuando un comentario comienza con un guión doble y no va seguido de un corchete largo de apertura [, se trata de un comentario corto. Continúa hasta el final de la línea. En caso contrario, se trata de un comentario largo. Continúa hasta un corchete largo de cierre. El comentario largo se utiliza frecuentemente para desactivar temporalmente una parte del código.
Lua es un lenguaje con definición dinámica de tipos. Una variable en Lua puede almacenar valores de cualquier tipo. No hay forma de declarar un tipo definido por el usuario. Un valor en Lua puede ser almacenado como una variable, pasado como argumento de una función y ser un valor de retorno de una función.
Hay ocho tipos principales en Lua: nil (indefinido), boolean, number, string, function, userdata (datos definidos por el usuario), thread and table. nil es del tipo nil [vacio]. El propósito principal de nil es diferenciarse de otros valores y designar la falta de un valor válido. Los valores false y true son del tipo boolean. Los valores nil y false son considerados valores falsos, cualquier otro valor es verdadero. number es un tipo de valor de coma flotante de doble precisión. Array de caracteres tiene tipo string. Las cadenas en Lua pueden contener cualquier carácter de 8 bytes, incluyendo el carácter nulo '\0' (ver §2.1).
Lua puede utilizar una función implementada como código Lua, o una función suministrada por el host (ver §2.5.8).
Una instancia userdata (datos definidos por el usuario)) almacena cualquier dato propiedad del host. El valor de dicha instancia es una referencia a un bloque de memoria. Sólo se permiten operadores de asignación e igualdad para variables de tipo `userdata`. Sin embargo, utilizando )metatablas), el desarrollador puede definir operaciones con variables de este tipo (véase §2.8). El código Lua no puede crear o cambiar variables de tipo `userdata`, sólo el host puede hacerlo. Esto garantiza la integridad de los datos, propiedad del host.
El tipo table define matrices asociativas. Como índices de dichas matrices pueden utilizarse tanto números como otros valores, excepto nil. La tabla puede contener valores de varios tipos simultáneamente (excepto nil). Las tablas son la única forma de estructurar los datos en Lua; pueden usarse como arrays simples, mapas de caracteres, conjuntos, estructuras, árboles, etc. Para implementar un diccionario, Lua utiliza claves como índices de una tabla. La expresión `a.nombre` es equivalente a la expresión `a["nombre"]`. En Lua existen varias formas de crear tablas (véase §2.5.7).
Los índices y valores de las tablas pueden ser de cualquier tipo excepto nil. Y como las funciones también son un tipo de Lua, las tablas pueden contener funciones. Por tanto, las tablas pueden almacenar métodos (véase §2.5.9).
Una variable de los siguientes tipos: table, function, thread y userdata, nunca almacena un valor propio. Dicha variable almacena referencia al objeto respectivo. La asignación (directa o pasando argumentos a una función o devolviendo el resultado de una función) procesa referencias y nunca crea copias de objetos.
La función type devuelve una cadena que contiene el tipo de valor.
Lua convierte automáticamente los tipos de cadena y numéricos sobre la marcha. Cuando se realiza una operación aritmética con un operando de cadena, éste se convierte al número respectivo utilizando tipos de conversión generales. Cuando se aplica un número donde se espera una cadena, ésta se convierte al tipo cadena en un formato arbitrario apropiado. Por lo tanto, cuando necesite obtener una representación de cadena específica de un número, debe utilizar la función format de la librería de cadenas de Lua (véase string.format).
Las variables almacenan valores mientras se ejecuta un programa. Existen tres tipos de variables en Lua: variables globales, variables locales y campos de tablas.
Un identificador individual declara una variable global o local (o parámetro de función, que es un caso particular de variable local):
var ::= Name
, donde Nombre es un identificador definido de acuerdo con §2.1.
Si una variable no se ha definido explícitamente como local, se considera una variable global (ver §2.4.7). Una variable local existe en un contexto léxico: cualquier función de este contexto puede acceder a la variable local. (ver §2.6).
Todas las variables se inician, por defecto, con el valor nil.
Para acceder a un elemento de una tabla por su índice, se utilizan corchetes:
var ::= prefixexp '[' exp ']'
Lua soporta el conjunto de operadores estándar, casi el mismo que lenguajes como Pascal y C. Lua dispone de operadores de asignación, control de flujo de ejecución, llamada a funciones y definición de variables.
Chunk es una unidad de ejecución en Lua. Un chunk es una secuencia de cualquier operador de Lua. Los operadores en un chunk están delimitados por punto y coma:
chunk ::= {stat [';']}
Lua no define "ningún operador", por lo tanto la expresión `;;` no está permitida.
Desde la perspectiva de Lua un chunk es una función sin nombre con un conjunto arbitrario de parámetros (véase §2.5.9). Un chunk puede definir variables locales y puede devolver valores.
Block es una lista de operadores; un bloque es sintácticamente equivalente a un chunk:
block ::= chunk
Un bloque puede definirse explícitamente y, por tanto, definir el operador compuesto:
stat ::= do block end
Los operadores compuestos permiten limitar el ámbito de las variables locales. Los operadores compuestos también se utilizan en bucles y operadores condicionales (ver §2.4.4).
Lua soporta la asignación paralela. En el caso general, el operador de asignación es la lista de variables, el símbolo `=` y la lista de expresiones. Las entradas de la lista están delimitadas por comas:
stat ::= varlist1 '=' explist1
varlist1 ::= var {',' var}
explist1 ::= exp {',' exp}
Las expresiones se tratan en §2.5.
Antes de ser asignada, la lista de variables se ajusta con la lista de expresiones por su longitud. Si la lista de la derecha es más larga que la de la izquierda, los elementos sobrantes simplemente se ignoran. Si la lista de la derecha es más corta, los elementos que faltan se definen como nulos (nil). Si la lista de operadores termina con una llamada a una función, antes del ajuste, todos los valores de retorno se añaden a la lista de la derecha (excepto en los casos en que la llamada a la función esté entre paréntesis; ver §2.5).
Todas las expresiones se evalúan antes de la asignación. En el siguiente código:
i = 3
i, a[i] = i + 1, 20
a `a[3]` se le asigna 20, porque `i` en la expresión `a[i]` tiene el mismo valor, que en la expresión `i + 1`, cuando está siendo evaluada. Del mismo modo, la siguiente línea
x, y = y, x
simplemente intercambia los valores de dos variables (el método "clásico" requiere una variable temporal).
Los operadores if, while y repeat tienen un significado y una sintaxis familiar :
stat ::= while exp do block end
stat ::= repeat block until exp
stat ::= if exp then block {elseif exp then block} [else block] end
Existen dos variantes del bucle for en Lua (ver §2.4.5).
Una expresión booleana en estructuras de control puede tener cualquier valor. false y nil son valores falsos. Todo lo demás es verdadero (¡incluidos 0 y una cadena vacía!).
El bucle repeat-until termina en la condición seguida de la palabra clave until. Por lo tanto, la condición del bucle puede utilizar variables locales del ámbito del bucle.
El operador return devuelve el valor de una función o chunk. La sintaxis del operador return permite devolver múltiples valores de una función o chunk:
stat ::= return [explist1]
El operador break finaliza un bucle while, repeat o for:
stat ::= break
break sale de un bucle, en cuyo ámbito se escribe `break`; los bucles exteriores continúan la ejecución.
return (o break) debe ser el último operador de un bloque (de lo contrario, se ignorarán todos los operadores siguientes). Si necesita return o break dentro de un bloque, debe utilizar un operador compuesto, como `do return end` o `do break end`.
El operador for tiene una notación sencilla y otra ampliada.
En su notación más simple, for ejecuta código mientras su variable de bucle, que se modifica mediante una progresión aritmética, no alcanza un límite definido.
stat ::= for Name ' = ' exp1 ',' exp2 [', ' exp3] do block end
El bucle ejecuta repetidamente block para la variable de bucle name, que inicialmente tiene el valor exp1, incrementa name en exp3 en cada iteración, mientras que exp2 se evalúa a valor verdadero.
Así, el siguiente código
for v = e1, e2, e3 do block end
es equivalente a
do
local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
if not (var and limit and step) then error() end
while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
local v = var
block
var = var + step
end
end
Cabe señalar que:
La notación extendida del operador for utiliza funciones iteradoras. En cada iteración del bucle se llama al iterador para obtener un nuevo valor para la variable del bucle. El bucle termina cuando su iterador devuelve nil. Sintaxis de la notación extendida del operador for:
stat ::= for namelist in explist1 do block end
namelist ::= Name {', '~ Name}
El siguiente código
for var_1, ···, var_n in explist do block end
puede ser escrito como
do
local f, s, var = explist
while true do
local var_1, ···, var_n = f(s, var)
var = var_1
if var == nil then break end
block
end
end
Conviene reseñar que:
Para crear un efecto lateral, puede ser útil llamar a funciones, utilizadas como operadores:
stat ::= functioncall
En este caso se ignoran todos los valores de retorno. Las llamadas a funciones se tratan en §2.5.8.
Las variables locales se declaran en cualquier lugar dentro de un bloque. La declaración puede incluir la inicialización:
stat ::= local namelist ['=' explist1]
La inicialización tiene todas las propiedades de la operación de asignación (incluido el paralelismo), §2.4.3. Por defecto, cualquier variable se inicializa con nil.
Un chunk es un bloque (ver §2.4.1), por lo que se puede declarar una variable local fuera de cualquier bloque explícito. El ámbito de dicha variable local son los límites del chunk.
Las reglas de visibilidad de las variables locales se tratan en §2.6.
Las siguientes construcciones son expresiones Lua:
exp ::= prefixexp
exp ::= nil | false | true
exp ::= Number
exp ::= String
exp ::= function
exp ::= tableconstructor
exp ::= '...'
exp ::= exp binop exp
exp ::= unop exp
prefixexp ::= var | functioncall | '(' exp ')'
Los números y las cadenas se tratan en §2.1; las variables -- en §2.1; la declaración de funciones -- en §2.5.9; la llamada a funciones -- en §2.5.8; el constructor de tablas -- en §2.5.7. Los argumentos implícitos, que se definen como `...`, sólo pueden utilizarse con la función correctamente declarada; ver §2.5.9.
Las operaciones binarias (binop) incluyen las operaciones aritméticas (ver §2.5.1, de comparación (ver §2.5.2), booleanas (ver §2.5.3) y de concatenación (ver §2.5.4). Las operaciones unarias incluyen el menos unario (ver §2.5.1), la negación not(ver §2.5.3) y la consulta de longitud # (ver §2.5.1).
El resultado de la llamada a una función y los parámetros implícitos pueden contener varios valores. Si se utilizan como operadores (§2.4.6) (sólo funciones), se ignora cualquier valor de retorno. Si es el último o el único elemento de la lista de expresiones, no se realiza ninguna corrección (si la llamada no está encerrada entre paréntesis). En todos los demás casos, Lua convierte la lista de retorno en un único elemento desechando todos los valores excepto el primero.
He aquí algunos ejemplos:
f() -- el resultado de la función se ignora
g(f(), x) -- sólo cuenta el primer valor de la lista - es el resultado de `f()`.
g(x, f()) -- g toma el valor de x y todos los valores de f()
a,b,c = f(), x -- obtiene el primer elemento del resultado de la llamada a `f()` (`c` obtiene `nil`)
a,b = ... -- `a` obtiene el primer argumento de `...`, `b` - el segundo (tanto `a` como `b` pueden obtener `nil`,
-- cuando la lista implícita de parámetros está vacía)
a,b,c = x, f() -- dos resultados de f()
a,b,c = f() -- tres resultados de f()
return f() -- devuelve todos los valores de f()
return ... -- devuelve todos los argumentos implícitos
return x,y,f() -- devuelve `x`, `y` y todos los resultados de f()
{f()} -- crear una lista con los resultados de f()
{...} -- crear una lista con todos los parámetros implícitos
{f(), nil} -- resultado único de f()
Una expresión encerrada entre paréntesis siempre devuelve un único valor. Así, `(f(x,y,z))` siempre da un único valor, incluso si `f` devuelve varios valores. El valor de `(f(x,y,z))` es el primer valor que devuelve `f`, o `nil` cuando `f` no devuelve ningún valor.
Lua soporta aritmética general: binaria, + (suma), - (resta), * (multiplicación), / (división), % (resto en la división) y ^ (potenciación); unario - (inversión del signo de un número). Cuando los operandos son números o cadenas (que son convertibles a números §2.2.1), todas las operaciones funcionan sin problemas. Funciones de potencia para cualquier exponente de potencia. Así, x^(-0.5) calcula el valor de la raíz cuadrada de `x`.
Las siguientes son las operaciones de comparación de Lua:
== ~= < > <= >=
Las operaciones de comparación siempre devuelven false o true.
El operador de igualdad (`==`) compara primero los tipos de los operandos. Cuando los tipos son diferentes, el operador devuelve false. En caso contrario, el operador compara los valores de los operandos. Los números y las cadenas se comparan de la forma habitual. Los objetos (tablas, tipos de datos definidos usados, hilos y funciones) se comparan por referencia: dos objetos son iguales cuando son el mismo objeto. Un objeto recién creado (tabla, tipo de datos definido, subproceso o función) no puede ser igual a un objeto ya existente.
Las reglas de conversión de §2.2.1 no afectan a los operadores de igualdad. Por ejemplo, `"0"==0` devuelve false, mientras que `t[0]` y `t["0"]` son dos registros de tabla diferentes.
El operador `~=` es el opuesto al operador de igualdad `==`.
Los operadores menor o mayor funcionan de la siguiente manera. Los números se comparan como de costumbre. Las cadenas se comparan en orden lexicográfico. Todos los demás casos provocarán la llamada del metamétodo (no se trata en este manual).
Lua soporta las siguientes operaciones lógicas: and, or y not. Al igual que las estructuras de control §2.4.4), las operaciones lógicas consideran false y nil como falso y todo lo demás como verdadero.
La operación de negación not siempre devuelve false o true. Operación de conjunción and devuelve su primer operando si valor del primer operando es false o nil; en caso contrario y devuelve el segundo operando. La operación de disyunción or devuelve el primer operando cuando el valor del primer operando no es igual a false ni a nil; en caso contrario or devuelve el segundo argumento. Ambos operadores evalúan el segundo operando sólo si es necesario.
Ejemplos:
10 or 20 --> 10
10 or error() --> 10
nil or "a" --> "a"
nil and 10 --> nil
false and error() --> false
false and nil --> false
false or nil --> nil
10 and 20 --> 20
(En este manual --> muestra el resultado de la evaluación)
El operador de concatenación de cadenas en Lua son dos puntos: `..`. Cuando ambos operandos son números o cadenas, se convertirán en cadenas según las reglas descritas en §2.2.1. En caso contrario se llama al metamétodo `.` (no se trata en este manual).
El operador unario # obtiene la longitud. Esta operación devuelve el número de bytes de una cadena (en el sentido habitual, es la longitud de una cadena en la que cada carácter ocupa un byte).
Cualquier índice integral `n` es la longitud de la tabla `t`, cuando t[n] no es nil pero t[n+1] es nil. Además, `#t = 0` si t[1] es nil. Para matrices de 1 a n, que no contengan nil, la longitud es `n`, es decir, el índice del último valor. Cuando una matriz tiene "huecos" (valores nulos entre valores no nulos), `#t` es el índice de un elemento, seguido del valor nulo (por tanto, cualquier valor nulo es el final de la matriz propiamente dicho).
La siguiente tabla muestra la precedencia de los operadores en Lua. La potenciación tiene la mayor prioridad y luego en orden descendente:
or
and
< > <= >= ~= ==
..
+ -
* / %
not # - (unary)
^
Para cambiar el orden de evaluación de una expresión se utilizan paréntesis. La concatenación ('..') y la potenciación ('^') son operadores asociativos a la derecha. Todos los demás operadores binarios son asociativos a la izquierda.
El constructor de tabla es una expresión. Cualquier constructor de tabla en código provoca la creación de una nueva tabla. Los constructores pueden crear tablas vacías o inicializadas parcial o totalmente. Esta es la sintaxis del constructor de tabla:
tableconstructor ::= '{' [fieldlist] '}'
fieldlist ::= field {fieldsep field} [fieldsep]
field ::= '[' exp ']' '=' exp | Name '=' exp | exp
fieldsep ::= ',' | ';'
Cada campo, escrito como `[exp1] = exp2`, añade el valor `exp2` con la clave `exp1` a la tabla. El campo `nombre = exp` es equivalente al campo `[["nombre["] = exp`. El campo `exp` es equivalente a [i] = exp, donde `i` es un contador entero autoincrementado con semilla igual a 1. Los campos definidos en otros formatos no afectan a este contador. Por ejemplo, la siguiente definición:
a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
es equivalente a
do
local t = {}
t[f(1)] = g
t[1] = "x"
t[2] = "y"
t.x = 1
t[3] = f(x)
t[30] = 23
t[4] = 45
a = t
end
Si el último campo de la lista de definiciones se declaró como `exp`, y `exp` es una llamada a función o una lista de parámetros indefinidos, todos los valores devueltos por esta expresión se añaden secuencialmente a esta lista ((§2.5.8)). Para evitar esto, encierre la llamada a función (o lista de parámetros indefinidos) entre paréntesis (§2.5).
La lista de campos puede terminar con un delimitador. Esto hace que el código generado sea más legible.
La llamada a una función en Lua tiene la siguiente sintaxis:
functioncall ::= prefixexp args
La expresión prefija y los argumentos se evalúan primero en una llamada a función. Cuando la expresión prefijada es de tipo función, se llama a la función con los argumentos suministrados. De lo contrario, se llama a metamehod (no se trata en este manual).
La siguiente notación
functioncall ::= prefixexp ':' Name args
puede utilizarse para llamar a "métodos" `v: name` expresión (args) es una sintaxis análoga a `v.name` (`v,args`), pero `v` se evalúa sólo una vez.
He aquí la definición de los argumentos:
args ::= '(' [explist1] ')'
args ::= tableconstructor
args ::= String
Todas las expresiones se evalúan antes de realizar la llamada. Una llamada realizada mediante la expresión `f{campos}` es un análogo de la expresión `f ({campos})`; por lo tanto, la lista de argumentos es una nueva tabla per se. Una llamada realizada por `f'cadena'` (o `f "cadena"`, o `f[[cadena]]`) es un análogo de `f('cadena')`; pero en este caso un único literal de cadena es una lista de argumentos
La sintaxis poco precisa de Lua tiene una excepción: no se puede añadir un salto de línea justo antes de `(` cuando se llama a una función. Esta excepción evita la ambigüedad en Lua. Si escribieras
a = f
(g).x(a)
Lua procesa esto como al expresión `a = f(g).x(a)`. Si todavía necesita dos expresiones, debe añadir un punto y coma entre las expresiones. Si realmente necesita llamar a la función `f`, debe eliminar el salto de línea antes de `(g)`.
Una llamada final es cuando se llama a una función con `return function call`. Lua soporta la auto-llamada final (o llamada final recursiva): en este caso el llamante usa la pila del llamador. Por tanto, el número de llamadas finales recursivas no está limitado. Cabe destacar que una llamada final elimina la información de depuración sobre el invocador. La sintaxis de la llamada final sólo permite llamar a una única función, mencionada después del operador return. Así, return da el mismo resultado que la función. No hay llamada final válida en el siguiente ejemplo:
return (f(x)) -- result list get truncated
return 2 * f(x) -- el resultado se duplica
return x, f(x) -- se devuelven varios valores
f(x); return -- el resultado de la llamada se ignora
return x or f(x) -- result list get truncated
Esta es la sintaxis de declaración de funciones:
function ::= function funcbody
funcbody ::= '(' [parlist1] ')' block end
O, en una versión más simplificada:
stat ::= function funcname funcbody
stat ::= local function Name funcbody
funcname ::= Name {'.' Name} [':' Name]
La expresión
function f () body end
es evaluada como
f = function () body end
La expresión
function t.a.b.c.f () body end
es evaluada como
t.a.b.c.f = function () body end
La expresión
local function f () body end
es evaluada com
local f; f = function () body end
pero no como
local f = function () body end
La diferencia aparecerá cuando el cuerpo de la función utilice el mismo nombre de función, por ejemplo, en una llamada de recursión.
La declaración de funciones es una expresión evaluada, su tipo es el tipo de la función. Cuando Lua precompila un chunk, todas las funciones en el chunk son también precompiladas. Así, cuando Lua procesa una declaración de función, la función ya está instanciada (o cerrada). Esta instancia (o cierre) es el valor final de la expresión "declaración de función". Diferentes instancias de la misma función pueden referirse a diferentes variables locales externas y tener diferentes tablas de entorno.
Los argumentos de las funciones son variables locales propiamente dichas; se inicializan con los valores de los argumentos:
parlist1 ::= namelist [',' '...'] | '...'
Cuando se llama a una función, la longitud de la lista de argumentos pasada se ajusta según la declaración, si la función no es una función con lista de argumentos variable. No se realiza ningún ajuste para las funciones con lista de argumentos variable; todos los argumentos se pasan como resultado múltiple de la función. Cuando una expresión indefinida se utiliza dentro de otra expresión o dentro de una lista de expresiones, su lista de valores se trunca en una entrada. Cuando dicha expresión es la última de la lista de expresiones, no se realiza el truncamiento (pero sólo si la llamada no está encerrada entre paréntesis).
Examinemos las siguientes declaraciones:
function f(a, b) end
function g(a, b, ...) end
function r() return 1,2,3 end
Este es un ejemplo de cómo se asignan los argumentos a los parámetros de una función:
CALL PARAMETERS
f(3) a=3, b=nil
f(3, 4) a=3, b=4
f(3, 4, 5) a=3, b=4
f(r(), 10) a=1, b=10
f(r()) a=1, b=2
g(3) a=3, b=nil, ... --> (nada)
g(3, 4) a=3, b=4, ... --> (nada)
g(3, 4, 5, 8) a=3, b=4, ... --> 5 8
g(5, r()) a=5, b=1, ... --> 2 3
Una función devuelve su resultado con el operador return (ver §2.4.4). Si se omite el operador return, y el flujo de ejecución llega al final de la función, ésta se completa pero no devuelve ningún valor.
La sintaxis con dos puntos (`:`) se utiliza cuando es necesario definir métodos. Tales funciones reciben `self` como primer argumento implícito. Así, la expresión:
function t.a.b.c:f (params) body end
es similar a:
t.a.b.c.f = function (self, params) body end
Lua es un lenguaje con delimitación léxica de ámbitos. El ámbito de una variable comienza después de la declaración de la variable y existe hasta el final del bloque donde la variable fue declarada. Examinemos el siguiente ejemplo:
x = 10 -- una variable global
do -- inicio de un bloque
local x = x -- declaración de una variable local
print(x) --> 10
x = x+1
do -- inicio de un bloque cerrado
local x = x+1 -- otra variable local 'x'
print(x) --> 12
end
print(x) --> 11
end
print(x) --> 10 (variable global)
Cabe destacar que en la declaración `local x = x`, la variable local se declara en ámbito ajeno, por lo que se asigna valor a la variable externa.
Según las reglas de delimitación léxica de los ámbitos, las variables locales son accesibles para las funciones declaradas en los ámbitos de las variables. Cuando una función utiliza una variable de este tipo, la variable se denomina variable local externa (relativa a una función declarada en el ámbito de la variable).
Cada declaración local crea una nueva variable local. Por ejemplo:
a = {}
local x = 20
for i=1,10 do
local y = 0
a[i] = function () y=y+1; return x+y end
end
El bucle crea diez instancias de la función, que utilizan diferentes variables `y` y la misma variable `x`.
Lua es un lenguaje de extensión, por lo tanto, Lua comienza a funcionar cuando un código anfitrión ha llamado a la función de la biblioteca de Lua lua_pcall. Si se produce un error mientras el código Lua está siendo compilado o ejecutado, la aplicación anfitriona obtiene el control de la ejecución y realiza la gestión del error (muestra un mensaje de error, por ejemplo)
El programa Lua puede generar un error explícitamente, llamando a la función error. Si desea manejar errores en el propio código Lua, utilice la función pcall.
Lua gestiona los recursos de memoria automáticamente. Esto significa que no tienes que preocuparte de la asignación de memoria cuando creas un objeto, y de la liberación de memoria una vez que un objeto se vuelve innecesario. Lua ejecuta un recolector de basura cada cierto tiempo, que elimina en segundo plano los objetos obsoletos (es decir, los objetos que ya no son accesibles desde el código Lua). El recolector de basura procesa todos los objetos de Lua: tablas, instancias de datos de usuario, funciones, hilos y cadenas.
Tipos de datos:
`void` es un argumento o resultado de función vacío;
`int` es un argumento entero o el resultado de una función;
`string` es un argumento de cadena o el resultado de una función;
`boolean` es un argumento booleano o el resultado de una función.
Atención: la primera entrada de cualquier lista de base de datos tiene índice cero. Por lo tanto, para enumerar todos los registros de la base de datos, por ejemplo, debe utilizar el siguiente código:
for i = 0, get_records_count() - 1 do -- i.e. número de elementos "-1"
...
end
Cualquier estructura de base de datos se maneja mediante punteros. Un puntero es una variable especial, que almacena (se refiere a) alguna ubicación de memoria donde se encuentra una estructura.
Existen los siguientes tipos de punteros a estructuras: