Lua - Guía rápida

Lua es un lenguaje de programación extensible y ligero escrito en C. Comenzó como un proyecto interno en 1993 por Roberto Ierusalimschy, Luiz Henrique de Figueiredo y Waldemar Celes.

Fue diseñado desde el principio para ser un software que se pueda integrar con el código escrito en C y otros lenguajes convencionales. Esta integración trae muchos beneficios. No intenta hacer lo que C ya puede hacer, pero apunta a ofrecer lo que C no es bueno: una buena distancia del hardware, estructuras dinámicas, sin redundancias, facilidad de prueba y depuración. Para ello, Lua cuenta con un entorno seguro, gestión automática de memoria y buenas instalaciones para manejar cadenas y otros tipos de datos con tamaño dinámico.

Caracteristicas

Lua proporciona un conjunto de características únicas que lo distingue de otros idiomas. Estos incluyen:

  • Extensible
  • Simple
  • Efficient
  • Portable
  • Libre y abierto

Código de ejemplo

print("Hello World!")

¿Cómo se implementa Lua?

Lua consta de dos partes: la parte del intérprete de Lua y el sistema de software en funcionamiento. El sistema de software en funcionamiento es una aplicación informática real que puede interpretar programas escritos en el lenguaje de programación Lua. El intérprete de Lua está escrito en ANSI C, por lo que es muy portátil y puede ejecutarse en un amplio espectro de dispositivos, desde servidores de red de alta gama hasta dispositivos pequeños.

Tanto el lenguaje de Lua como su intérprete son maduros, pequeños y rápidos. Ha evolucionado a partir de otros lenguajes de programación y los mejores estándares de software. Al ser de tamaño pequeño, es posible que se ejecute en dispositivos pequeños con poca memoria.

Aprendiendo a Lua

El punto más importante al aprender Lua es concentrarse en los conceptos sin perderse en sus detalles técnicos.

El propósito de aprender un lenguaje de programación es convertirse en un mejor programador; es decir, volverse más eficaces en el diseño e implementación de nuevos sistemas y en el mantenimiento de los antiguos.

Algunos usos de Lua

  • Programación de juegos

  • Secuencias de comandos en aplicaciones independientes

  • Scripting en Web

  • Extensiones y complementos para bases de datos como MySQL Proxy y MySQL WorkBench

  • Sistemas de seguridad como el sistema de detección de intrusiones.

Configuración del entorno local

Si todavía está dispuesto a configurar su entorno para el lenguaje de programación Lua, necesita los siguientes softwares disponibles en su computadora: (a) Editor de texto, (b) The Lua Interpreter y (c) Lua Compiler.

Editor de texto

Necesita un editor de texto para escribir su programa. Algunos ejemplos de algunos editores incluyen el Bloc de notas de Windows, el comando de edición del sistema operativo, Brief, Epsilon, EMACS y vim o vi.

El nombre y la versión del editor de texto pueden variar en diferentes sistemas operativos. Por ejemplo, el Bloc de notas se utilizará en Windows y vim o vi se pueden utilizar en Windows, así como en Linux o UNIX.

Los archivos que crea con su editor se denominan archivos fuente y estos archivos contienen el código fuente del programa. Los archivos de origen de los programas Lua generalmente se nombran con la extensión".lua".

El intérprete de Lua

Es solo un pequeño programa que le permite escribir comandos Lua y ejecutarlos inmediatamente. Detiene la ejecución de un archivo Lua en caso de que encuentre un error a diferencia de un compilador que se ejecuta completamente.

El compilador de Lua

Cuando extendemos Lua a otros lenguajes / aplicaciones, necesitamos un kit de desarrollo de software con un compilador que sea compatible con la interfaz del programa de aplicación Lua.

Instalación en Windows

Existe un IDE separado llamado "SciTE" desarrollado para el entorno de Windows, que se puede descargar desde https://code.google.com/p/luaforwindows/ sección de descargas.

Ejecute el ejecutable descargado para instalar Lua IDE.

Dado que es un IDE, puede crear y compilar el código Lua utilizando el mismo.

En caso de que esté interesado en instalar Lua en modo de línea de comandos, debe instalar MinGW o Cygwin y luego compilar e instalar Lua en Windows.

Instalación en Linux

Para descargar y compilar Lua, use el siguiente comando:

$ wget http://www.lua.org/ftp/lua-5.2.3.tar.gz $ tar zxf lua-5.2.3.tar.gz
$ cd lua-5.2.3 $ make linux test

Para instalar en otras plataformas como aix, ansi, bsd, linux genérico, mingw, posix, solaris reemplazando Linux en make Linux, pruebe con el nombre de plataforma correspondiente.

Tenemos un helloWorld.lua, en Lua de la siguiente manera:

print("Hello World!")

Ahora, podemos construir y ejecutar un archivo Lua, digamos helloWorld.lua, cambiando a la carpeta que contiene el archivo usando cd, y luego usando el siguiente comando:

$ lua helloWorld

Podemos ver el siguiente resultado.

Hello World!

Instalación en Mac OS X

Para construir / probar Lua en Mac OS X, use el siguiente comando:

$ curl -R -O http://www.lua.org/ftp/lua-5.2.3.tar.gz
$ tar zxf lua-5.2.3.tar.gz $ cd lua-5.2.3
$ make macosx test

En ciertos casos, es posible que no haya instalado Xcode y las herramientas de línea de comandos. En tales casos, no podrá utilizar el comando make. Instale Xcode desde la tienda de aplicaciones mac. Luego vaya a Preferencias de Xcode, luego cambie a Descargas e instale el componente llamado "Herramientas de línea de comandos". Una vez que se complete el proceso, el comando make estará disponible para usted.

No es obligatorio que ejecute la instrucción "make macosx test". Incluso sin ejecutar este comando, aún puede usar Lua en Mac OS X.

Tenemos un helloWorld.lua, en Lua, de la siguiente manera:

print("Hello World!")

Ahora, podemos construir y ejecutar un archivo Lua, digamos holaWorld.lua, cambiando a la carpeta que contiene el archivo usando cd y luego usando el siguiente comando:

$ lua helloWorld

Podemos ver la siguiente salida:

Hello World!

Lua IDE

Como se mencionó anteriormente, para Windows SciTE, Lua IDE es el IDE predeterminado proporcionado por el equipo creador de Lua. El IDE alternativo disponible es de ZeroBrane Studio, que está disponible en múltiples plataformas como Windows, Mac y Linux.

También hay complementos para eclipse que permiten el desarrollo de Lua. El uso de IDE facilita el desarrollo con funciones como la finalización de código y es muy recomendable. El IDE también proporciona programación en modo interactivo similar a la versión de línea de comandos de Lua.

¡Comencemos a crear nuestro primer programa Lua!

Primer programa Lua

Programación en modo interactivo

Lua proporciona un modo llamado modo interactivo. En este modo, puede escribir instrucciones una tras otra y obtener resultados instantáneos. Esto se puede invocar en el shell usando lua -i o simplemente el comando lua. Una vez que escriba esto, presione Entrar y el modo interactivo se iniciará como se muestra a continuación.

$ lua -i $ Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
quit to end; cd, dir and edit also available

Puede imprimir algo usando la siguiente declaración:

print("test")

Una vez que presione enter, obtendrá el siguiente resultado:

test

Programación de modo predeterminado

La invocación del intérprete con un parámetro de nombre de archivo Lua comienza la ejecución del archivo y continúa hasta que finaliza el script. Cuando finaliza el guión, el intérprete ya no está activo.

Escribamos un programa simple de Lua. Todos los archivos Lua tendrán la extensión .lua. Así que ponga el siguiente código fuente en un archivo test.lua.

print("test")

Suponiendo que el entorno lua está configurado correctamente, ejecutemos el programa usando el siguiente código:

$ lua test.lua

Obtendremos el siguiente resultado:

test

Probemos otra forma de ejecutar un programa Lua. A continuación se muestra el archivo test.lua modificado:

#!/usr/local/bin/lua

print("test")

Aquí, hemos asumido que tiene un intérprete de Lua disponible en su directorio / usr / local / bin. El intérprete ignora la primera línea, si comienza con el signo #. Ahora, intente ejecutar este programa de la siguiente manera:

$ chmod a+rx test.lua
$./test.lua

Obtendremos el siguiente resultado.

test

Veamos ahora la estructura básica del programa Lua, para que le resulte fácil comprender los componentes básicos del lenguaje de programación Lua.

Fichas en Lua

Un programa Lua consta de varios tokens y un token es una palabra clave, un identificador, una constante, una cadena literal o un símbolo. Por ejemplo, la siguiente declaración de Lua consta de tres tokens:

io.write("Hello world, from ",_VERSION,"!\n")

Los tokens individuales son:

io.write
(
   "Hello world, from ",_VERSION,"!\n"
)

Comentarios

Los comentarios son como texto de ayuda en su programa Lua y el intérprete los ignora. Comienzan con - [[y terminan con los caracteres -]] como se muestra a continuación -

--[[ my first program in Lua --]]

Identificadores

Un identificador Lua es un nombre que se usa para identificar una variable, función o cualquier otro elemento definido por el usuario. Un identificador comienza con una letra 'A a Z' o 'a a z' o un guión bajo '_' seguido de cero o más letras, guiones bajos y dígitos (0 a 9).

Lua no permite caracteres de puntuación como @, $ y% dentro de los identificadores. Lua es unacase sensitivelenguaje de programación. Por tanto, la mano de obra y la mano de obra son dos identificadores diferentes en Lua. A continuación, se muestran algunos ejemplos de identificadores aceptables:

mohd         zara      abc     move_name    a_123
myname50     _temp     j       a23b9        retVal

Palabras clave

La siguiente lista muestra algunas de las palabras reservadas en Lua. Estas palabras reservadas no se pueden utilizar como constantes o variables o cualquier otro nombre de identificador.

y romper hacer más
elseif fin falso para
función Si en local
nulo no o repetir
regreso luego cierto hasta
mientras

Espacio en blanco en Lua

Una línea que contiene solo espacios en blanco, posiblemente con un comentario, se conoce como línea en blanco y un intérprete de Lua la ignora por completo.

Espacio en blanco es el término utilizado en Lua para describir espacios en blanco, tabulaciones, caracteres de nueva línea y comentarios. El espacio en blanco separa una parte de una declaración de otra y permite al intérprete identificar dónde termina un elemento de una declaración, como int, y comienza el siguiente elemento. Por lo tanto, en la siguiente declaración:

local age

Debe haber al menos un carácter de espacio en blanco (generalmente un espacio) entre el local y la edad para que el intérprete pueda distinguirlos. Por otro lado, en la siguiente declaración:

fruit = apples + oranges   --get the total fruit

No se necesitan espacios en blanco entre fruta y =, o entre = y manzanas, aunque puede incluir algunos si lo desea por motivos de legibilidad.

Una variable no es más que un nombre que se le da a un área de almacenamiento que nuestros programas pueden manipular. Puede contener diferentes tipos de valores, incluidas funciones y tablas.

El nombre de una variable puede estar compuesto por letras, dígitos y el carácter de subrayado. Debe comenzar con una letra o un guión bajo. Las letras mayúsculas y minúsculas son distintas porque Lua distingue entre mayúsculas y minúsculas. Hay ocho tipos básicos de valores en Lua:

En Lua, aunque no tenemos tipos de datos variables, tenemos tres tipos según el alcance de la variable.

  • Global variables - Todas las variables se consideran globales a menos que se declaren explícitamente como locales.

  • Local variables - Cuando el tipo se especifica como local para una variable, su alcance está limitado con las funciones dentro de su alcance.

  • Table fields - Este es un tipo especial de variable que puede contener cualquier cosa excepto nil, incluidas funciones.

Definición de variable en Lua

Una definición de variable significa decirle al intérprete dónde y cuánto crear el almacenamiento para la variable. Una definición de variable tiene un tipo opcional y contiene una lista de una o más variables de ese tipo de la siguiente manera:

type variable_list;

Aquí, type es opcionalmente local o de tipo especificado, lo que lo hace global, y variable_listpuede constar de uno o más nombres de identificadores separados por comas. Aquí se muestran algunas declaraciones válidas:

local    i, j
local    i
local    a,c

La línea local i, jdeclara y define las variables i y j; que indica al intérprete que cree variables denominadas i, jy limita el alcance para que sea local.

Las variables se pueden inicializar (asignar un valor inicial) en su declaración. El inicializador consta de un signo igual seguido de una expresión constante de la siguiente manera:

type variable_list = value_list;

Algunos ejemplos son:

local d , f = 5 ,10     --declaration of d and f as local variables. 
d , f = 5, 10;          --declaration of d and f as global variables. 
d, f = 10               --[[declaration of d and f as global variables. 
                           Here value of f is nil --]]

Para la definición sin un inicializador: las variables con duración de almacenamiento estático se inicializan implícitamente con nil.

Declaración de variable en Lua

Como puede ver en los ejemplos anteriores, las asignaciones para múltiples variables siguen un formato de lista_variable y lista_valor. En el ejemplo anteriorlocal d, f = 5,10 tenemos d y f en lista_variable y 5 y 10 en lista de valores.

La asignación de valor en Lua tiene lugar como la primera variable en la lista_variable con el primer valor en la lista_valor y así sucesivamente. Por tanto, el valor de d es 5 y el valor de f es 10.

Ejemplo

Pruebe el siguiente ejemplo, donde las variables se han declarado en la parte superior, pero se han definido e inicializado dentro de la función principal:

-- Variable definition:
local a, b

-- Initialization
a = 10
b = 30

print("value of a:", a)

print("value of b:", b)

-- Swapping of variables
b, a = a, b

print("value of a:", a)

print("value of b:", b)

f = 70.0/3.0
print("value of f", f)

Cuando se crea y ejecuta el código anterior, produce el siguiente resultado:

value of a:	10
value of b:	30
value of a:	30
value of b:	10
value of f	23.333333333333

Valores L y valores R en Lua

Hay dos tipos de expresiones en Lua:

  • lvalue- Las expresiones que se refieren a una ubicación de memoria se denominan expresión "lvalue". Un lvalue puede aparecer como el lado izquierdo o derecho de una tarea.

  • rvalue- El término rvalue se refiere a un valor de datos que se almacena en alguna dirección de la memoria. Un rvalue es una expresión que no puede tener un valor asignado, lo que significa que un rvalue puede aparecer en el lado derecho, pero no en el lado izquierdo de una asignación.

Las variables son valores l y, por lo tanto, pueden aparecer en el lado izquierdo de una tarea. Los literales numéricos son valores r y, por lo tanto, no se pueden asignar y no pueden aparecer en el lado izquierdo. A continuación se muestra una declaración válida:

g = 20

Pero lo siguiente no es una declaración válida y generaría un error en el tiempo de compilación:

10 = 20

En el lenguaje de programación Lua, además de los tipos de asignación anteriores, es posible tener múltiples valores l y r en la misma declaración. Se muestra a continuación.

g,l = 20,30

En la declaración anterior, 20 se asigna a gy 30 se asigna a l.

Lua es un lenguaje escrito dinámicamente, por lo que las variables no tienen tipos, solo los valores tienen tipos. Los valores pueden almacenarse en variables, pasarse como parámetros y devolverse como resultados.

En Lua, aunque no tenemos tipos de datos variables, tenemos tipos para los valores. La lista de tipos de datos para valores se da a continuación.

No Señor Tipo de valor y descripción
1

nil

Se utiliza para diferenciar el valor de tener algunos datos o no tener datos (nulos).

2

boolean

Incluye verdadero y falso como valores. Generalmente se utiliza para comprobar el estado.

3

number

Representa números reales (punto flotante de doble precisión).

4

string

Representa una matriz de caracteres.

5

function

Representa un método que está escrito en C o Lua.

6

userdata

Representa datos C arbitrarios.

7

thread

Representa hilos de ejecución independientes y se utiliza para implementar corrutinas.

8

table

Representa matrices ordinarias, tablas de símbolos, conjuntos, registros, gráficos, árboles, etc., e implementa matrices asociativas. Puede contener cualquier valor (excepto nulo).

Función de tipo

En Lua, existe una función llamada 'tipo' que nos permite conocer el tipo de variable. En el siguiente código se dan algunos ejemplos.

print(type("What is my type"))   --> string
t = 10

print(type(5.8*t))               --> number
print(type(true))                --> boolean
print(type(print))               --> function
print(type(nil))                 --> nil
print(type(type(ABC)))           --> string

Cuando compila y ejecuta el programa anterior, produce el siguiente resultado en Linux:

string
number
boolean
function
nil
string

De forma predeterminada, todas las variables apuntarán a cero hasta que se les asigne un valor o se inicialicen. En Lua, las cadenas de cero y vacías se consideran verdaderas en caso de verificaciones de condición. Por lo tanto, debe tener cuidado al usar operaciones booleanas. Sabremos más sobre el uso de estos tipos en los próximos capítulos.

Un operador es un símbolo que le dice al intérprete que realice manipulaciones matemáticas o lógicas específicas. El lenguaje Lua es rico en operadores integrados y proporciona el siguiente tipo de operadores:

  • Operadores aritméticos
  • Operadores relacionales
  • Operadores logicos
  • Operadores varios

Este tutorial explicará los operadores aritméticos, relacionales, lógicos y otros, uno por uno.

Operadores aritméticos

La siguiente tabla muestra todos los operadores aritméticos compatibles con el lenguaje Lua. Asumir variableA tiene 10 y variable B sostiene 20 entonces -

Mostrar ejemplos

Operador Descripción Ejemplo
+ Agrega dos operandos A + B dará 30
- Resta el segundo operando del primero A - B dará -10
* Multiplica ambos operandos A * B dará 200
/ Dividir numerador por numerador B / A dará 2
% Operador de módulo y resto de después de una división entera B% A dará 0
^ El operador de exponentes toma los exponentes A ^ 2 dará 100
- Unario: el operador actúa como negación -A dará -10

Operadores relacionales

La siguiente tabla muestra todos los operadores relacionales compatibles con el lenguaje Lua. Asumir variableA tiene 10 y variable B sostiene 20 entonces -

Mostrar ejemplos

Operador Descripción Ejemplo
== Comprueba si el valor de dos operandos es igual o no, si es así, la condición se convierte en verdadera. (A == B) no es cierto.
~ = Comprueba si el valor de dos operandos es igual o no, si los valores no son iguales, la condición se convierte en verdadera. (A ~ = B) es cierto.
> Comprueba si el valor del operando izquierdo es mayor que el valor del operando derecho, si es así, la condición se convierte en verdadera. (A> B) no es cierto.
< Comprueba si el valor del operando izquierdo es menor que el valor del operando derecho, si es así, la condición se convierte en verdadera. (A <B) es cierto.
> = Comprueba si el valor del operando izquierdo es mayor o igual que el valor del operando derecho, si es así, la condición se convierte en verdadera. (A> = B) no es cierto.
<= Comprueba si el valor del operando izquierdo es menor o igual que el valor del operando derecho, si es así, la condición se convierte en verdadera. (A <= B) es cierto.

Operadores logicos

La siguiente tabla muestra todos los operadores lógicos compatibles con el lenguaje Lua. Asumir variableA se mantiene verdadero y variable B se mantiene falso entonces -

Mostrar ejemplos

Operador Descripción Ejemplo
y Operador llamado lógico AND. Si ambos operandos son distintos de cero, la condición se vuelve verdadera. (A y B) es falso.
o Operador OR lógico llamado. Si alguno de los dos operandos es distinto de cero, la condición se cumple. (A o B) es cierto.
no Operador llamado lógico NOT. Úselo para revertir el estado lógico de su operando. Si una condición es verdadera, el operador NOT lógico la convertirá en falsa. ! (A y B) es cierto.

Operadores varios

Los operadores misceláneos compatibles con Lua Language incluyen concatenation y length.

Mostrar ejemplos

Operador Descripción Ejemplo
.. Concatena dos cadenas. a..b donde a es "Hola" yb es "Mundo", devolverá "Hola mundo".
# Un operador unario que devuelve la longitud de una cadena o una tabla. # "Hola" devolverá 5

Precedencia de operadores en Lua

La precedencia del operador determina la agrupación de términos en una expresión. Esto afecta cómo se evalúa una expresión. Ciertos operadores tienen mayor precedencia que otros; por ejemplo, el operador de multiplicación tiene mayor precedencia que el operador de suma -

Por ejemplo, x = 7 + 3 * 2; Aquí x se asigna 13, no 20 porque el operador * tiene mayor precedencia que +, por lo que primero se multiplica por 3 * 2 y luego se suma a 7.

Aquí, los operadores con mayor precedencia aparecen en la parte superior de la tabla, los que tienen la menor prioridad aparecen en la parte inferior. Dentro de una expresión, los operadores de mayor precedencia se evaluarán primero.

Mostrar ejemplos

Categoría Operador Asociatividad
Unario no # - De derecha a izquierda
Concatenación .. De derecha a izquierda
Multiplicativo * /% De izquierda a derecha
Aditivo + - De izquierda a derecha
Relacional <> <=> = == ~ =  De izquierda a derecha
Igualdad == ~ = De izquierda a derecha
Y lógico y De izquierda a derecha
OR lógico o De izquierda a derecha

Puede haber una situación en la que necesite ejecutar un bloque de código varias veces. En general, las sentencias se ejecutan secuencialmente: la primera sentencia de una función se ejecuta primero, seguida de la segunda, y así sucesivamente.

Los lenguajes de programación proporcionan varias estructuras de control que permiten rutas de ejecución más complicadas.

Una declaración de bucle nos permite ejecutar una declaración o grupo de declaraciones varias veces. A continuación se muestra la forma general de una declaración de bucle en la mayoría de los lenguajes de programación:

Lua proporciona los siguientes tipos de bucles para manejar los requisitos de bucle.

No Señor. Tipo de bucle y descripción
1 while loop

Repite una declaración o un grupo de declaraciones mientras una condición determinada es verdadera. Prueba la condición antes de ejecutar el cuerpo del bucle.

2 en bucle

Ejecuta una secuencia de declaraciones varias veces y abrevia el código que administra la variable de ciclo.

3 repetir ... hasta bucle

Repite la operación del grupo de declaraciones hasta que se cumpla la condición hasta que se cumpla.

4 bucles anidados

Puede utilizar uno o más bucles dentro de cualquier otro bucle while, for o do.. while.

Declaración de control de bucle

La instrucción de control de bucle cambia la ejecución de su secuencia normal. Cuando la ejecución abandona un ámbito, todos los objetos automáticos que se crearon en ese ámbito se destruyen.

Lua admite las siguientes declaraciones de control.

No Señor. Declaración de control y descripción
1 declaración de ruptura

Termina el loop y transfiere la ejecución a la instrucción que sigue inmediatamente al bucle o cambio.

El bucle infinito

Un bucle se convierte en bucle infinito si una condición nunca se vuelve falsa. loswhileloop se utiliza a menudo para este propósito. Dado que directamente damos verdadero a la condición, se sigue ejecutando para siempre. Podemos usar la instrucción break para romper este ciclo.

while( true )
do
   print("This loop will run forever.")
end

Las estructuras de toma de decisiones requieren que el programador especifique una o más condiciones para ser evaluadas o probadas por el programa, junto con una declaración o declaraciones que se ejecutarán, si se determina que la condición es verdadera, y opcionalmente, otras declaraciones que se ejecutarán si el se determina que la condición es falsa.

A continuación se muestra la forma general de una estructura de toma de decisiones típica que se encuentra en la mayoría de los lenguajes de programación:

El lenguaje de programación Lua asume cualquier combinación de booleanos true y non-nil valores como true, y si es booleano false o nil, entonces se asume como falsevalor. Cabe señalar que en Lua,zero will be considered as true.

El lenguaje de programación Lua proporciona los siguientes tipos de declaraciones para la toma de decisiones.

No Señor. Declaración y descripción
1 si declaración

Una declaración if consta de una expresión booleana seguida de una o más declaraciones.

2 declaración if ... else

Una instrucción if puede ir seguida de una instrucción else opcional , que se ejecuta cuando la expresión booleana es falsa.

3 declaraciones if anidadas

Puede usar una instrucción if o else if dentro de otra instrucción if o else if .

Una función es un grupo de declaraciones que juntas realizan una tarea. Puede dividir su código en funciones separadas. La forma en que divide su código entre las diferentes funciones depende de usted, pero lógicamente la división generalmente es única, es decir, cada función realiza una tarea específica.

El lenguaje Lua proporciona numerosos métodos integrados que su programa puede llamar. Por ejemplo, métodoprint() para imprimir el argumento pasado como entrada en la consola.

Una función se conoce con varios nombres como método, subrutina, procedimiento, etc.

Definición de una función

La forma general de una definición de método en el lenguaje de programación Lua es la siguiente:

optional_function_scope function function_name( argument1, argument2, argument3........, 
argumentn)
function_body
return result_params_comma_separated
end

Una definición de método en el lenguaje de programación Lua consta de un encabezado de método y un cuerpo de método . Aquí están todas las partes de un método:

  • Optional Function Scope- Puede usar la palabra clave local para limitar el alcance de la función o ignorar la sección de alcance, lo que la convertirá en una función global.

  • Function Name- Este es el nombre real de la función. El nombre de la función y la lista de parámetros juntos constituyen la firma de la función.

  • Arguments- Un argumento es como un marcador de posición. Cuando se invoca una función, se pasa un valor al argumento. Este valor se denomina parámetro o argumento real. La lista de parámetros se refiere al tipo, orden y número de argumentos de un método. Los argumentos son opcionales; es decir, un método puede no contener ningún argumento.

  • Function Body - El cuerpo del método contiene una colección de declaraciones que definen lo que hace el método.

  • Return - En Lua, es posible devolver múltiples valores siguiendo la palabra clave return con los valores de retorno separados por comas.

Ejemplo

A continuación se muestra el código fuente de una función llamada max(). Esta función toma dos parámetros num1 y num2 y devuelve el máximo entre los dos -

--[[ function returning the max between two numbers --]]
function max(num1, num2)

   if (num1 > num2) then
      result = num1;
   else
      result = num2;
   end

   return result; 
end

Argumentos de función

Si una función va a utilizar argumentos, debe declarar las variables que aceptan los valores de los argumentos. Estas variables se denominanformal parameters de la función.

Los parámetros formales se comportan como otras variables locales dentro de la función y se crean al entrar en la función y se destruyen al salir.

Llamar a una función

Al crear una función Lua, da una definición de lo que tiene que hacer la función. Para utilizar un método, tendrá que llamar a esa función para realizar la tarea definida.

Cuando un programa llama a una función, el control del programa se transfiere a la función llamada. Una función llamada realiza la tarea definida y cuando se ejecuta su declaración de retorno o cuando se alcanza el final de su función, devuelve el control del programa al programa principal.

Para llamar a un método, simplemente necesita pasar los parámetros requeridos junto con el nombre del método y si el método devuelve un valor, entonces puede almacenar el valor devuelto. Por ejemplo

function max(num1, num2)

   if (num1 > num2) then
      result = num1;
   else
      result = num2;
   end

   return result; 
end

-- calling a function
print("The maximum of the two numbers is ",max(10,4))
print("The maximum of the two numbers is ",max(5,6))

Cuando ejecutamos el código anterior, obtendremos el siguiente resultado.

The maximum of the two numbers is 	10
The maximum of the two numbers is 	6

Asignar y pasar funciones

En Lua, podemos asignar la función a variables y también podemos pasarlas como parámetros de otra función. Aquí hay un ejemplo simple para asignar y pasar una función como parámetro en Lua.

myprint = function(param)
   print("This is my print function -   ##",param,"##")
end

function add(num1,num2,functionPrint)
   result = num1 + num2
   functionPrint(result)
end

myprint(10)
add(2,5,myprint)

Cuando ejecutamos el código anterior, obtendremos el siguiente resultado.

This is my print function -   ##	10	##
This is my print function -   ##	7	##

Función con argumento variable

Es posible crear funciones con argumentos variables en Lua usando '...' como parámetro. Podemos comprender esto al ver un ejemplo en el que la función devolverá el promedio y puede tomar argumentos variables.

function average(...)
   result = 0
   local arg = {...}
   for i,v in ipairs(arg) do
      result = result + v
   end
   return result/#arg
end

print("The average is",average(10,5,3,4,5,6))

Cuando ejecutamos el código anterior, obtendremos el siguiente resultado.

The average is	5.5

La cadena es una secuencia de caracteres, así como caracteres de control como el avance de formulario. La cadena se puede inicializar con tres formas que incluyen:

  • Caracteres entre comillas simples
  • Caracteres entre comillas dobles
  • Caracteres entre [[y]]

A continuación se muestra un ejemplo de los tres formularios anteriores.

string1 = "Lua"
print("\"String 1 is\"",string1)

string2 = 'Tutorial'
print("String 2 is",string2)

string3 = [["Lua Tutorial"]]
print("String 3 is",string3)

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

"String 1 is" Lua
String 2 is	Tutorial
String 3 is	"Lua Tutorial"

Los caracteres de la secuencia de escape se utilizan en una cadena para cambiar la interpretación normal de los caracteres. Por ejemplo, para imprimir comas dobles invertidas (""), hemos usado \ "en el ejemplo anterior. La secuencia de escape y su uso se enumeran a continuación en la tabla.

Secuencia de escape Utilizar
\un Campana
\segundo Retroceso
\F Formfeed
\norte Nueva línea
\ r Retorno de carro
\ t Lengüeta
\ v Pestaña vertical
\\ Barra invertida
\ " Doble comillas
\ ' Comillas simples
\ [ Corchete izquierdo
\] Corchete derecho

Manipulación de cuerdas

Lua admite cuerdas para manipular cuerdas -

No Señor. Método y propósito
1

string.upper(argument)

Devuelve una representación del argumento en mayúscula.

2

string.lower(argument)

Devuelve una representación en minúsculas del argumento.

3

string.gsub(mainString,findString,replaceString)

Devuelve una cadena reemplazando las apariciones de findString con replaceString.

4

string.find(mainString,findString,

optionalStartIndex,optionalEndIndex)

Devuelve el índice inicial y el índice final de findString en la cadena principal y nulo si no se encuentra.

5

string.reverse(arg)

Devuelve una cadena invirtiendo los caracteres de la cadena pasada.

6

string.format(...)

Devuelve una cadena formateada.

7

string.char(arg) and string.byte(arg)

Devuelve representaciones internas numéricas y de caracteres del argumento de entrada.

8

string.len(arg)

Devuelve una longitud de la cadena pasada.

9

string.rep(string, n))

Devuelve una cadena repitiendo la misma cadena n veces.

10

..

Por lo tanto, el operador concatena dos cadenas.

Ahora, profundicemos en algunos ejemplos para ver exactamente cómo se comportan estas funciones de manipulación de cadenas.

Manipulación de casos

A continuación se proporciona un código de muestra para manipular las cadenas en mayúsculas y minúsculas.

string1 = "Lua";

print(string.upper(string1))
print(string.lower(string1))

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

LUA
lua

Reemplazo de una subcadena

A continuación, se proporciona un código de muestra para reemplazar las ocurrencias de una cadena por otra.

string = "Lua Tutorial"

-- replacing strings
newstring = string.gsub(string,"Tutorial","Language")
print("The new string is "..newstring)

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

The new string is Lua Language

Encontrar y revertir

A continuación se proporciona un código de muestra para encontrar el índice de subcadena y cadena de inversión.

string = "Lua Tutorial"

-- replacing strings
print(string.find(string,"Tutorial"))
reversedString = string.reverse(string)
print("The new string is",reversedString)

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

5	12
The new string is	lairotuT auL

Formateo de cadenas

Muchas veces en nuestra programación, es posible que necesitemos imprimir cadenas de forma formateada. Puede utilizar la función string.format para formatear la salida como se muestra a continuación.

string1 = "Lua"
string2 = "Tutorial"

number1 = 10
number2 = 20

-- Basic string formatting
print(string.format("Basic formatting %s %s",string1,string2))

-- Date formatting
date = 2; month = 1; year = 2014
print(string.format("Date formatting %02d/%02d/%03d", date, month, year))

-- Decimal formatting
print(string.format("%.4f",1/3))

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

Basic formatting Lua Tutorial
Date formatting 02/01/2014
0.3333

Representaciones de caracteres y bytes

Un código de muestra para la representación de caracteres y bytes, que se utiliza para convertir la cadena de cadena en representación interna y viceversa.

-- Byte conversion

-- First character
print(string.byte("Lua"))

-- Third character
print(string.byte("Lua",3))

-- first character from last
print(string.byte("Lua",-1))

-- Second character
print(string.byte("Lua",2))

-- Second character from last
print(string.byte("Lua",-2))

-- Internal Numeric ASCII Conversion
print(string.char(97))

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

76
97
97
117
117
a

Otras funciones comunes

Las manipulaciones comunes de cadenas incluyen la concatenación de cadenas, encontrar la longitud de la cadena y, en ocasiones, repetir la misma cadena varias veces. El ejemplo de estas operaciones se da a continuación.

string1 = "Lua"
string2 = "Tutorial"

-- String Concatenations using ..
print("Concatenated string",string1..string2)

-- Length of string
print("Length of string1 is ",string.len(string1))

-- Repeating strings
repeatedString = string.rep(string1,3)
print(repeatedString)

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

Concatenated string	LuaTutorial
Length of string1 is 	3
LuaLuaLua

Las matrices son una disposición ordenada de objetos, que puede ser una matriz unidimensional que contiene una colección de filas o una matriz multidimensional que contiene varias filas y columnas.

En Lua, las matrices se implementan mediante tablas de indexación con números enteros. El tamaño de una matriz no es fijo y puede crecer según nuestros requisitos, sujeto a restricciones de memoria.

Matriz unidimensional

Una matriz unidimensional se puede representar usando una estructura de tabla simple y se puede inicializar y leer usando un simple forlazo. A continuación se muestra un ejemplo.

array = {"Lua", "Tutorial"}

for i = 0, 2 do
   print(array[i])
end

Cuando ejecutamos el código anterior, obtendremos el siguiente resultado.

nil
Lua
Tutorial

Como puede ver en el código anterior, cuando intentamos acceder a un elemento en un índice que no está en la matriz, devuelve nil. En Lua, la indexación generalmente comienza en el índice 1. Pero también es posible crear objetos en el índice 0 y por debajo de 0. La matriz que usa índices negativos se muestra a continuación, donde inicializamos la matriz usando un bucle for .

array = {}

for i= -2, 2 do
   array[i] = i *2
end

for i = -2,2 do
   print(array[i])
end

Cuando ejecutamos el código anterior, obtendremos el siguiente resultado.

-4
-2
0
2
4

Matriz multidimensional

Las matrices multidimensionales se pueden implementar de dos formas.

  • Matriz de matrices
  • Matriz unidimensional manipulando índices

A continuación se muestra un ejemplo de matriz multidimensional de 3. 3 utilizando una matriz de matrices.

-- Initializing the array
array = {}

for i=1,3 do
   array[i] = {}
	
   for j=1,3 do
      array[i][j] = i*j
   end
	
end

-- Accessing the array

for i=1,3 do

   for j=1,3 do
      print(array[i][j])
   end
	
end

Cuando ejecutamos el código anterior, obtendremos el siguiente resultado.

1
2
3
2
4
6
3
6
9

A continuación se muestra un ejemplo de matriz multidimensional mediante la manipulación de índices.

-- Initializing the array

array = {}

maxRows = 3
maxColumns = 3

for row=1,maxRows do

   for col=1,maxColumns do
      array[row*maxColumns +col] = row*col
   end
	
end

-- Accessing the array

for row=1,maxRows do

   for col=1,maxColumns do
      print(array[row*maxColumns +col])
   end
	
end

Cuando ejecutamos el código anterior, obtendremos el siguiente resultado.

1
2
3
2
4
6
3
6
9

Como puede ver en el ejemplo anterior, los datos se almacenan en función de índices. Es posible colocar los elementos de forma dispersa y así funciona la implementación de Lua de una matriz. Dado que no almacena valores nulos en Lua, es posible ahorrar mucha memoria sin ninguna técnica especial en Lua en comparación con las técnicas especiales utilizadas en otros lenguajes de programación.

Iterator es una construcción que le permite atravesar los elementos de la denominada colección o contenedor. En Lua, estas colecciones a menudo se refieren a tablas, que se utilizan para crear varias estructuras de datos como matrices.

Genérico para iterador

Un iterador genérico para proporciona los pares clave-valor de cada elemento de la colección. A continuación se ofrece un ejemplo sencillo.

array = {"Lua", "Tutorial"}

for key,value in ipairs(array) 
do
   print(key, value)
end

Cuando ejecutamos el código anterior, obtendremos el siguiente resultado:

1  Lua
2  Tutorial

El ejemplo anterior usa la función de iterador ipairs predeterminada proporcionada por Lua.

En Lua usamos funciones para representar iteradores. Según el mantenimiento del estado en estas funciones de iterador, tenemos dos tipos principales:

  • Iteradores sin estado
  • Iteradores con estado

Iteradores sin estado

Por el nombre mismo podemos entender que este tipo de función iteradora no retiene ningún estado.

Veamos ahora un ejemplo de cómo crear nuestro propio iterador usando una función simple que imprime los cuadrados de n números.

function square(iteratorMaxCount,currentNumber)

   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
      return currentNumber, currentNumber*currentNumber
   end
	
end

for i,n in square,3,0
do
   print(i,n)
end

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

1	1
2	4
3	9

El código anterior se puede modificar ligeramente para imitar la forma en que funciona la función ipairs de los iteradores. Se muestra a continuación.

function square(iteratorMaxCount,currentNumber)

   if currentNumber<iteratorMaxCount
   then
      currentNumber = currentNumber+1
      return currentNumber, currentNumber*currentNumber
   end
	
end

function squares(iteratorMaxCount)
   return square,iteratorMaxCount,0
end  

for i,n in squares(3)
do 
   print(i,n)
end

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

1	1
2	4
3	9

Iteradores con estado

El ejemplo anterior de iteración con función no conserva el estado. Cada vez que se llama a la función, devuelve el siguiente elemento de la colección basándose en una segunda variable enviada a la función. Para mantener el estado del elemento actual, se utilizan cierres. El cierre retiene los valores de las variables en las llamadas a funciones. Para crear un nuevo cierre, creamos dos funciones, incluido el cierre en sí y una fábrica, la función que crea el cierre.

Veamos ahora un ejemplo de cómo crear nuestro propio iterador en el que usaremos cierres.

array = {"Lua", "Tutorial"}

function elementIterator (collection)

   local index = 0
   local count = #collection
	
   -- The closure function is returned
	
   return function ()
      index = index + 1
		
      if index <= count
      then
         -- return the current element of the iterator
         return collection[index]
      end
		
   end
	
end

for element in elementIterator(array)
do
   print(element)
end

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

Lua
Tutorial

En el ejemplo anterior, podemos ver que elementIterator tiene otro método dentro que usa el índice de variables externas locales y cuenta para devolver cada uno de los elementos de la colección incrementando el índice cada vez que se llama a la función.

Podemos crear nuestros propios iteradores de funciones usando el cierre como se muestra arriba y puede devolver múltiples elementos para cada una de las veces que iteramos a través de la colección.

Introducción

Las tablas son la única estructura de datos disponible en Lua que nos ayuda a crear diferentes tipos como matrices y diccionarios. Lua usa matrices asociativas y que se pueden indexar no solo con números sino también con cadenas, excepto nil. Las mesas no tienen un tamaño fijo y pueden crecer según nuestras necesidades.

Lua usa tablas en todas las representaciones, incluida la representación de paquetes. Cuando accedemos a un método string.format, significa que estamos accediendo a la función de formato disponible en el paquete string.

Representación y uso

Las tablas se llaman objetos y no son valores ni variables. Lua usa una expresión de constructor {} para crear una tabla vacía. Debe saberse que no existe una relación fija entre una variable que contiene la referencia de la tabla y la tabla en sí.

--sample table initialization
mytable = {}

--simple table value assignment
mytable[1]= "Lua"

--removing reference
mytable = nil

-- lua garbage collection will take care of releasing memory

Cuando tenemos una mesa a con conjunto de elementos y si lo asignamos a b, ambos a y bse refieren a la misma memoria. No se asigna memoria separada por separado para b. Cuando a se establece en cero, la tabla seguirá siendo accesible para b. Cuando no hay referencia a una tabla, la recolección de basura en Lua se encarga del proceso de limpieza para hacer que esta memoria sin referencia se reutilice nuevamente.

A continuación se muestra un ejemplo para explicar las características de las tablas mencionadas anteriormente.

-- Simple empty table
mytable = {}
print("Type of mytable is ",type(mytable))

mytable[1]= "Lua"
mytable["wow"] = "Tutorial"

print("mytable Element at index 1 is ", mytable[1])
print("mytable Element at index wow is ", mytable["wow"])

-- alternatetable and mytable refers to same table
alternatetable = mytable

print("alternatetable Element at index 1 is ", alternatetable[1])
print("alternatetable Element at index wow is ", alternatetable["wow"])

alternatetable["wow"] = "I changed it"

print("mytable Element at index wow is ", mytable["wow"])

-- only variable released and and not table
alternatetable = nil
print("alternatetable is ", alternatetable)

-- mytable is still accessible
print("mytable Element at index wow is ", mytable["wow"])

mytable = nil
print("mytable is ", mytable)

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado:

Type of mytable is 	table
mytable Element at index 1 is 	Lua
mytable Element at index wow is 	Tutorial
alternatetable Element at index 1 is 	Lua
alternatetable Element at index wow is 	Tutorial
mytable Element at index wow is 	I changed it
alternatetable is 	nil
mytable Element at index wow is 	I changed it
mytable is 	nil

Manipulación de mesa

Hay funciones integradas para la manipulación de tablas y se enumeran en la siguiente tabla.

No Señor. Método y propósito
1

table.concat (table [, sep [, i [, j]]])

Concatena las cadenas en las tablas según los parámetros dados. Consulte el ejemplo para obtener más detalles.

2

table.insert (table, [pos,] value)

Inserta un valor en la tabla en la posición especificada.

3

table.maxn (table)

Devuelve el índice numérico más grande.

4

table.remove (table [, pos])

Elimina el valor de la tabla.

5

table.sort (table [, comp])

Ordena la tabla según el argumento de comparación opcional.

Veamos algunos ejemplos de las funciones anteriores.

Concatenación de tablas

Podemos usar la función concat para concatenar dos tablas como se muestra a continuación:

fruits = {"banana","orange","apple"}

-- returns concatenated string of table
print("Concatenated string ",table.concat(fruits))

--concatenate with a character
print("Concatenated string ",table.concat(fruits,", "))

--concatenate fruits based on index
print("Concatenated string ",table.concat(fruits,", ", 2,3))

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado:

Concatenated string 	bananaorangeapple
Concatenated string 	banana, orange, apple
Concatenated string 	orange, apple

Insertar y quitar

La inserción y eliminación de elementos en tablas es más común en la manipulación de tablas. Se explica a continuación.

fruits = {"banana","orange","apple"}

-- insert a fruit at the end
table.insert(fruits,"mango")
print("Fruit at index 4 is ",fruits[4])

--insert fruit at index 2
table.insert(fruits,2,"grapes")
print("Fruit at index 2 is ",fruits[2])

print("The maximum elements in table is",table.maxn(fruits))

print("The last element is",fruits[5])

table.remove(fruits)
print("The previous last element is",fruits[5])

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado:

Fruit at index 4 is 	mango
Fruit at index 2 is 	grapes
The maximum elements in table is	5
The last element is	mango
The previous last element is	nil

Tablas de clasificación

A menudo requerimos ordenar una tabla en un orden particular. Las funciones de clasificación clasifican los elementos de una tabla alfabéticamente. A continuación se muestra un ejemplo de esto.

fruits = {"banana","orange","apple","grapes"}

for k,v in ipairs(fruits) do
   print(k,v)
end

table.sort(fruits)
print("sorted table")

for k,v in ipairs(fruits) do
   print(k,v)
end

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado:

1	banana
2	orange
3	apple
4	grapes
sorted table
1	apple
2	banana
3	grapes
4	orange

¿Qué es un módulo?

El módulo es como una biblioteca que se puede cargar usando require y tiene un solo nombre global que contiene una tabla. Este módulo puede constar de varias funciones y variables. Todas estas funciones y variables están incluidas en la tabla, que actúa como un espacio de nombres. Además, un módulo con buen comportamiento tiene las disposiciones necesarias para devolver esta tabla a require.

Especialidad de los módulos Lua

El uso de tablas en módulos nos ayuda de muchas formas y nos permite manipular los módulos de la misma forma que manipulamos cualquier otra tabla Lua. Como resultado de la capacidad de manipular módulos, proporciona funciones adicionales para las que otros lenguajes necesitan mecanismos especiales. Debido a este mecanismo gratuito de módulos en Lua, un usuario puede llamar a las funciones en Lua de múltiples formas. Algunos de ellos se muestran a continuación.

-- Assuming we have a module printFormatter
-- Also printFormatter has a funtion simpleFormat(arg)
-- Method 1
require "printFormatter"
printFormatter.simpleFormat("test")

-- Method 2
local formatter = require "printFormatter"
formatter.simpleFormat("test")

-- Method 3
require "printFormatter"
local formatterFunction = printFormatter.simpleFormat
formatterFunction("test")

En el código de muestra anterior, puede ver cuán flexible es la programación en Lua, sin ningún código adicional especial.

La función require

Lua ha proporcionado una función de alto nivel llamada require para cargar todos los módulos necesarios. Se mantiene lo más simple posible para evitar tener demasiada información en el módulo para cargarlo. La función require simplemente asume los módulos como un fragmento de código que define algunos valores, que en realidad son funciones o tablas que contienen funciones.

Ejemplo

Consideremos un ejemplo simple, donde una función tiene funciones matemáticas. Llamemos a este módulo mymath y el nombre de archivo es mymath.lua. El contenido del archivo es el siguiente:

local mymath =  {}

function mymath.add(a,b)
   print(a+b)
end

function mymath.sub(a,b)
   print(a-b)
end

function mymath.mul(a,b)
   print(a*b)
end

function mymath.div(a,b)
   print(a/b)
end

return mymath

Ahora, para acceder a este módulo de Lua en otro archivo, digamos, moduleutorial.lua, debe usar el siguiente segmento de código.

mymathmodule = require("mymath")
mymathmodule.add(10,20)
mymathmodule.sub(30,20)
mymathmodule.mul(10,20)
mymathmodule.div(30,20)

Para ejecutar este código, necesitamos colocar los dos archivos Lua en el mismo directorio o, alternativamente, puede colocar el archivo del módulo en la ruta del paquete y necesita una configuración adicional. Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

30
10
200
1.5

Cosas para recordar

  • Coloque tanto los módulos como el archivo que ejecuta en el mismo directorio.

  • El nombre del módulo y su nombre de archivo deben ser iguales.

  • Es una buena práctica devolver módulos para la función requerida y, por lo tanto, el módulo debe implementarse preferiblemente como se muestra arriba, aunque puede encontrar otros tipos de implementaciones en otros lugares.

Forma antigua de implementar módulos

Permítanme ahora reescribir el mismo ejemplo de la forma anterior, que usa package.seeall tipo de implementación. Esto se utilizó en las versiones 5.1 y 5.0 de Lua. El módulo mymath se muestra a continuación.

module("mymath", package.seeall)

function mymath.add(a,b)
   print(a+b)
end

function mymath.sub(a,b)
   print(a-b)
end

function mymath.mul(a,b)
   print(a*b)
end

function mymath.div(a,b)
   print(a/b)
end

A continuación, se muestra el uso de módulos en moduleutorial.lua.

require("mymath")
mymath.add(10,20)
mymath.sub(30,20)
mymath.mul(10,20)
mymath.div(30,20)

Cuando ejecutamos lo anterior, obtendremos el mismo resultado. Pero se recomienda utilizar la versión anterior del código y se supone que es menos segura. Muchos SDK que usan Lua para programación como Corona SDK han desaprobado el uso de esto.

Una metatabla es una tabla que ayuda a modificar el comportamiento de una tabla a la que está adjunta con la ayuda de un conjunto de claves y meta métodos relacionados. Estos meta métodos son una poderosa funcionalidad de Lua que habilita características como:

  • Cambiar / agregar funcionalidades a operadores en tablas.

  • Buscando metatablas cuando la clave no está disponible en la tabla usando __index en metatabla.

Hay dos métodos importantes que se utilizan en el manejo de metatablas que incluyen:

  • setmetatable(table,metatable) - Este método se utiliza para configurar metatabla para una tabla.

  • getmetatable(table) - Este método se utiliza para obtener metatabla de una tabla.

Primero veamos cómo establecer una tabla como metatabla de otra. Se muestra a continuación.

mytable = {}
mymetatable = {}
setmetatable(mytable,mymetatable)

El código anterior se puede representar en una sola línea como se muestra a continuación.

mytable = setmetatable({},{})

_índice

A continuación se muestra un ejemplo simple de metatabla para buscar la metatabla cuando no está disponible en la tabla.

mytable = setmetatable({key1 = "value1"}, {
   __index = function(mytable, key)
	
      if key == "key2" then
         return "metatablevalue"
      else
         return mytable[key]
      end
   end
})

print(mytable.key1,mytable.key2)

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

value1 metatablevalue

Expliquemos lo que sucedió en el ejemplo anterior en pasos.

  • La mesa mytable aquí es {key1 = "value1"}.

  • Metatable está configurado para mytable que contiene una función para __index, que llamamos como metamétodo.

  • El metamétodo hace un trabajo simple de buscar un índice "key2", si se encuentra, devuelve "metatablevalue"; de lo contrario, devuelve el valor de mytable para el índice correspondiente.

Podemos tener una versión simplificada del programa anterior como se muestra a continuación.

mytable = setmetatable({key1 = "value1"}, 
   { __index = { key2 = "metatablevalue" } })
print(mytable.key1,mytable.key2)

__nuevo índice

Cuando agregamos __newindex a la metatabla, si las claves no están disponibles en la tabla, el comportamiento de las nuevas claves será definido por los meta métodos. A continuación se muestra un ejemplo sencillo en el que se establece el índice de la metatabla cuando el índice no está disponible en la tabla principal.

mymetatable = {}
mytable = setmetatable({key1 = "value1"}, { __newindex = mymetatable })

print(mytable.key1)

mytable.newkey = "new value 2"
print(mytable.newkey,mymetatable.newkey)

mytable.key1 = "new  value 1"
print(mytable.key1,mymetatable.newkey1)

Cuando ejecuta el programa anterior, obtiene el siguiente resultado.

value1
nil	new value 2
new  value 1	nil

Puede ver en el programa anterior, si existe una clave en la tabla principal, simplemente la actualiza. Cuando una clave no está disponible en el mantenimiento, agrega esa clave a la metatabla.

A continuación se muestra otro ejemplo que actualiza la misma tabla utilizando la función rawset.

mytable = setmetatable({key1 = "value1"}, {

   __newindex = function(mytable, key, value)
      rawset(mytable, key, "\""..value.."\"")
   end
})

mytable.key1 = "new value"
mytable.key2 = 4

print(mytable.key1,mytable.key2)

Cuando ejecutamos el programa anterior obtendremos el siguiente resultado.

new value	"4"

rawset establece el valor sin usar __newindex de metatable. De manera similar, hay rawget que obtiene valor sin usar __index.

Agregar el comportamiento del operador a las tablas

A continuación se muestra un ejemplo simple para combinar dos tablas usando el operador +:

mytable = setmetatable({ 1, 2, 3 }, {
   __add = function(mytable, newtable)
	
      for i = 1, table.maxn(newtable) do
         table.insert(mytable, table.maxn(mytable)+1,newtable[i])
      end
      return mytable
   end
})

secondtable = {4,5,6}

mytable = mytable + secondtable

for k,v in ipairs(mytable) do
   print(k,v)
end

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

1	1
2	2
3	3
4	4
5	5
6	6

La clave __add se incluye en la metatabla para agregar el comportamiento del operador +. La tabla de llaves y operador correspondiente se muestra a continuación.

No Señor. Modo y descripción
1

__add

Cambia el comportamiento del operador '+'.

2

__sub

Cambia el comportamiento del operador '-'.

3

__mul

Cambia el comportamiento del operador '*'.

4

__div

Cambia el comportamiento del operador '/'.

5

__mod

Cambia el comportamiento del operador '%'.

6

__unm

Cambia el comportamiento del operador '-'.

7

__concat

Cambia el comportamiento del operador '..'.

8

__eq

Cambia el comportamiento del operador '=='.

9

__lt

Cambia el comportamiento del operador '<'.

10

__le

Cambia el comportamiento del operador '<='.

__llamada

La adición del comportamiento de la llamada al método se realiza mediante la instrucción __call. Un ejemplo simple que devuelve la suma de valores en la tabla principal con la tabla pasada.

mytable = setmetatable({10}, {
   __call = function(mytable, newtable)
   sum = 0
	
      for i = 1, table.maxn(mytable) do
         sum = sum + mytable[i]
      end
	
      for i = 1, table.maxn(newtable) do
         sum = sum + newtable[i]
      end
	
      return sum
   end
})

newtable = {10,20,30}
print(mytable(newtable))

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

70

__Encadenar

Para cambiar el comportamiento de la declaración de impresión, podemos usar el metamétodo __tostring. A continuación se muestra un ejemplo sencillo.

mytable = setmetatable({ 10, 20, 30 }, {
   __tostring = function(mytable)
   sum = 0
	
      for k, v in pairs(mytable) do
         sum = sum + v
      end
		
      return "The sum of values in the table is " .. sum
   end
})
print(mytable)

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

The sum of values in the table is 60

Si conoce completamente las capacidades de la metatabla, realmente puede realizar muchas operaciones que serían muy complejas sin usarla. Por lo tanto, intente trabajar más en el uso de metatablas con diferentes opciones disponibles en metatabla como se explica en las muestras y también cree sus propias muestras.

Introducción

Las corrutinas son de naturaleza colaborativa, lo que permite que dos o más métodos se ejecuten de manera controlada. Con las corrutinas, en un momento dado, solo se ejecuta una corrutina y esta corrutina en ejecución solo suspende su ejecución cuando solicita explícitamente ser suspendida.

La definición anterior puede parecer vaga. Supongamos que tenemos dos métodos, uno el método del programa principal y una corrutina. Cuando llamamos a una corrutina usando la función resume, comienza a ejecutarse y cuando llamamos a la función yield, suspende la ejecución. Nuevamente, la misma corrutina puede continuar ejecutándose con otra llamada de función de reanudación desde donde se suspendió. Este proceso puede continuar hasta el final de la ejecución de la corrutina.

Funciones disponibles en corrutinas

La siguiente tabla enumera todas las funciones disponibles para corrutinas en Lua y su uso correspondiente.

No Señor. Método y propósito
1

coroutine.create (f)

Crea una nueva corrutina con una función f y devuelve un objeto de tipo "hilo".

2

coroutine.resume (co [, val1, ...])

Reanuda la co-rutina co y pasa los parámetros si los hay. Devuelve el estado de funcionamiento y otros valores de retorno opcionales.

3

coroutine.running ()

Devuelve la corrutina en ejecución o nil si se llama en el hilo principal.

4

coroutine.status (co)

Devuelve uno de los valores de ejecución, normal, suspendido o muerto según el estado de la corrutina.

5

coroutine.wrap (f)

Al igual que coroutine.create, la función coroutine.wrap también crea una corrutina, pero en lugar de devolver la corrutina en sí, devuelve una función que, cuando se llama, reanuda la corrutina.

6

coroutine.yield (...)

Suspende la corrutina en ejecución. El parámetro pasado a este método actúa como valores de retorno adicionales a la función de reanudación.

Ejemplo

Veamos un ejemplo para entender el concepto de corrutinas.

co = coroutine.create(function (value1,value2)
   local tempvar3 = 10
   print("coroutine section 1", value1, value2, tempvar3)
	
   local tempvar1 = coroutine.yield(value1+1,value2+1)
   tempvar3 = tempvar3 + value1
   print("coroutine section 2",tempvar1 ,tempvar2, tempvar3)
	
   local tempvar1, tempvar2= coroutine.yield(value1+value2, value1-value2)
   tempvar3 = tempvar3 + value1
   print("coroutine section 3",tempvar1,tempvar2, tempvar3)
   return value2, "end"
	
end)

print("main", coroutine.resume(co, 3, 2))
print("main", coroutine.resume(co, 12,14))
print("main", coroutine.resume(co, 5, 6))
print("main", coroutine.resume(co, 10, 20))

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

coroutine section 1	3	2	10
main	true	4	3
coroutine section 2	12	nil	13
main	true	5	1
coroutine section 3	5	6	16
main	true	2	end
main	false	cannot resume dead coroutine

¿Qué hace el ejemplo anterior?

Como se mencionó anteriormente, usamos la función de reanudación para iniciar la operación y la función de rendimiento para detener la operación. Además, puede ver que hay varios valores de retorno recibidos por la función de reanudación de la rutina.

  • Primero, creamos una corrutina y le asignamos un nombre de variable co y la corrutina toma dos variables como parámetros.

  • Cuando llamamos a la primera función de reanudación, los valores 3 y 2 se retienen en las variables temporales value1 y value2 hasta el final de la corrutina.

  • Para hacerle entender esto, hemos usado un tempvar3, que es 10 inicialmente y se actualiza a 13 y 16 por las llamadas posteriores de las corrutinas, ya que value1 se retiene como 3 durante la ejecución de la corrutina.

  • La primera coroutine.yield devuelve dos valores 4 y 3 a la función resume, que obtenemos actualizando los parámetros de entrada 3 y 2 en la declaración yield. También recibe el estado verdadero / falso de la ejecución de una rutina.

  • Otra cosa acerca de las corrutinas es cómo se gestionan los siguientes parámetros de la llamada de reanudación, en el ejemplo anterior; puede ver que la variable coroutine.yield recibe los siguientes parámetros de llamada, lo que proporciona una forma poderosa de realizar una nueva operación con la retención de los valores de parámetro existentes.

  • Finalmente, una vez que se ejecutan todas las declaraciones en las corrutinas, las llamadas posteriores volverán en falso y la declaración "no se puede reanudar la corrutina muerta" como respuesta.

Otro ejemplo de corrutina

Veamos una corrutina simple que devuelve un número del 1 al 5 con la ayuda de la función de rendimiento y la función de reanudación. Crea una corrutina si no está disponible o reanuda la corrutina existente.

function getNumber()
   local function getNumberHelper()
      co = coroutine.create(function ()
      coroutine.yield(1)
      coroutine.yield(2)
      coroutine.yield(3)
      coroutine.yield(4)
      coroutine.yield(5)
      end)
      return co
   end
	
   if(numberHelper) then
      status, number = coroutine.resume(numberHelper);
		
      if coroutine.status(numberHelper) == "dead" then
         numberHelper = getNumberHelper()
         status, number = coroutine.resume(numberHelper);
      end
		
      return number
   else
      numberHelper = getNumberHelper()
      status, number = coroutine.resume(numberHelper);
      return number
   end
	
end

for index = 1, 10 do
   print(index, getNumber())
end

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

1	1
2	2
3	3
4	4
5	5
6	1
7	2
8	3
9	4
10	5

A menudo hay una comparación de las corrutinas con los subprocesos de los lenguajes de multiprogramación, pero debemos comprender que las corrutinas tienen características similares de subprocesos, pero se ejecutan solo una a la vez y nunca se ejecutan al mismo tiempo.

Controlamos la secuencia de ejecución del programa para satisfacer las necesidades con la disposición de retener cierta información temporalmente. El uso de variables globales con corrutinas proporciona aún más flexibilidad a las corrutinas.

La biblioteca de E / S se utiliza para leer y manipular archivos en Lua. Hay dos tipos de operaciones de archivo en Lua, a saber, descriptores de archivo implícitos y descriptores de archivo explícitos.

Para los siguientes ejemplos, usaremos un archivo de muestra test.lua como se muestra a continuación.

-- sample test.lua
-- sample2 test.lua

Una simple operación de apertura de archivo utiliza la siguiente declaración.

file = io.open (filename [, mode])

Los distintos modos de archivo se enumeran en la siguiente tabla.

No Señor. Modo y descripción
1

"r"

Modo de solo lectura y es el modo predeterminado donde se abre un archivo existente.

2

"w"

Modo de escritura habilitado que sobrescribe el archivo existente o crea un archivo nuevo.

3

"a"

Modo de agregar que abre un archivo existente o crea un nuevo archivo para agregar.

4

"r+"

Modo de lectura y escritura para un archivo existente.

5

"w+"

Todos los datos existentes se eliminan si el archivo existe o se crea un archivo nuevo con permisos de lectura y escritura.

6

"a+"

Modo de anexión con modo de lectura habilitado que abre un archivo existente o crea un archivo nuevo.

Descriptores de archivo implícitos

Los descriptores de archivo implícitos utilizan los modos de entrada / salida estándar o utilizan un archivo de entrada y salida única. A continuación, se muestra un ejemplo del uso de descriptores de archivo implícitos.

-- Opens a file in read
file = io.open("test.lua", "r")

-- sets the default input file as test.lua
io.input(file)

-- prints the first line of the file
print(io.read())

-- closes the open file
io.close(file)

-- Opens a file in append mode
file = io.open("test.lua", "a")

-- sets the default output file as test.lua
io.output(file)

-- appends a word test to the last line of the file
io.write("-- End of the test.lua file")

-- closes the open file
io.close(file)

Cuando ejecute el programa, obtendrá una salida de la primera línea del archivo test.lua. Para nuestro programa, obtuvimos el siguiente resultado.

-- Sample test.lua

Esta fue la primera línea de la declaración en el archivo test.lua para nosotros. Además, la línea "- Fin del archivo test.lua" se agregaría a la última línea del código test.lua.

En el ejemplo anterior, puede ver cómo funcionan los descriptores implícitos con el sistema de archivos utilizando los métodos io. "X". El ejemplo anterior usa io.read () sin el parámetro opcional. El parámetro opcional puede ser cualquiera de los siguientes.

No Señor. Modo y descripción
1

"*n"

Lee desde la posición actual del archivo y devuelve un número si existe en la posición del archivo o devuelve nulo.

2

"*a"

Devuelve todo el contenido del archivo desde la posición actual del archivo.

3

"*l"

Lee la línea desde la posición actual del archivo y mueve la posición del archivo a la siguiente línea.

4

number

Lee el número de bytes especificado en la función.

Otros métodos de E / S comunes incluyen,

  • io.tmpfile() - Devuelve un archivo temporal para lectura y escritura que se eliminará una vez que se cierre el programa.

  • io.type(file) - Devuelve si archivo, archivo cerrado o nulo según el archivo de entrada.

  • io.flush() - Borra el búfer de salida predeterminado.

  • io.lines(optional file name)- Proporciona un iterador de bucle for genérico que recorre el archivo y cierra el archivo al final, en caso de que se proporcione el nombre del archivo o se utilice el archivo predeterminado y no se cierre al final del bucle.

Descriptores de archivo explícitos

A menudo utilizamos un descriptor de archivo explícito que nos permite manipular varios archivos a la vez. Estas funciones son bastante similares a los descriptores de archivos implícitos. Aquí, usamos file: function_name en lugar de io.function_name. El siguiente ejemplo de la versión de archivo del mismo ejemplo de descriptores de archivo implícitos se muestra a continuación.

-- Opens a file in read mode
file = io.open("test.lua", "r")

-- prints the first line of the file
print(file:read())

-- closes the opened file
file:close()

-- Opens a file in append mode
file = io.open("test.lua", "a")

-- appends a word test to the last line of the file
file:write("--test")

-- closes the open file
file:close()

Cuando ejecute el programa, obtendrá un resultado similar al del ejemplo de descriptores implícitos.

-- Sample test.lua

Todos los modos de apertura de archivos y parámetros de lectura para descriptores externos son los mismos que los descriptores de archivos implícitos.

Otros métodos de archivo comunes incluyen,

  • file:seek(optional whence, optional offset)- De donde el parámetro es "set", "cur" o "end". Establece el puntero del nuevo archivo con la posición del archivo actualizado desde el principio del archivo. Las compensaciones se basan en cero en esta función. El desplazamiento se mide desde el principio del archivo si el primer argumento está "establecido"; desde la posición actual en el archivo si es "cur"; o desde el final del archivo si es "fin". Los valores predeterminados de los argumentos son "cur" y 0, por lo que la posición actual del archivo se puede obtener llamando a esta función sin argumentos.

  • file:flush() - Borra el búfer de salida predeterminado.

  • io.lines(optional file name)- Proporciona un iterador de bucle for genérico que recorre el archivo y cierra el archivo al final, en caso de que se proporcione el nombre del archivo o se utilice el archivo predeterminado y no se cierre al final del bucle.

A continuación se muestra un ejemplo para utilizar el método de búsqueda. Desplaza el cursor desde las 25 posiciones antes del final del archivo. La función de lectura imprime el resto del archivo desde la posición de búsqueda.

-- Opens a file in read
file = io.open("test.lua", "r")

file:seek("end",-25)
print(file:read("*a"))

-- closes the opened file
file:close()

Obtendrá un resultado similar al siguiente.

sample2 test.lua
--test

Puede jugar con todos los diferentes modos y parámetros para conocer la capacidad total de las operaciones del archivo Lua.

Necesidad de manejo de errores

El manejo de errores es bastante crítico ya que las operaciones del mundo real a menudo requieren el uso de operaciones complejas, que incluyen operaciones de archivos, transacciones de bases de datos y llamadas a servicios web.

En cualquier programación, siempre existe un requisito para el manejo de errores. Los errores pueden ser de dos tipos que incluyen,

  • Errores de sintaxis
  • Errores de tiempo de ejecución

Errores de sintaxis

Los errores de sintaxis ocurren debido al uso inadecuado de varios componentes del programa, como operadores y expresiones. A continuación, se muestra un ejemplo sencillo de error de sintaxis.

a == 2

Como saben, existe una diferencia entre el uso de un solo "igual a" y doble "igual a". Usar uno en lugar del otro puede provocar un error. Un "igual a" se refiere a la asignación, mientras que un doble "igual a" se refiere a la comparación. De manera similar, tenemos expresiones y funciones que tienen sus formas predefinidas de implementación.

Otro ejemplo de error de sintaxis se muestra a continuación:

for a= 1,10
   print(a)
end

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado:

lua: test2.lua:2: 'do' expected near 'print'

Los errores de sintaxis son mucho más fáciles de manejar que los errores de tiempo de ejecución, ya que el intérprete de Lua localiza el error con mayor claridad que en caso de error de tiempo de ejecución. A partir del error anterior, podemos saber fácilmente que se requiere agregar una declaración do antes de la declaración de impresión según la estructura de Lua.

Errores de tiempo de ejecución

En caso de errores de tiempo de ejecución, el programa se ejecuta correctamente, pero puede provocar errores de tiempo de ejecución debido a errores en la entrada o funciones mal manejadas. A continuación, se muestra un ejemplo sencillo para mostrar el error de tiempo de ejecución.

function add(a,b)
   return a+b
end

add(10)

Cuando construimos el programa, se construirá correctamente y se ejecutará. Una vez que se ejecuta, muestra un error de tiempo de ejecución.

lua: test2.lua:2: attempt to perform arithmetic on local 'b' (a nil value)
stack traceback:
	test2.lua:2: in function 'add'
	test2.lua:5: in main chunk
	[C]: ?

Este es un error de tiempo de ejecución, que se produjo debido a que no se pasaron dos variables. losb Se espera el parámetro y aquí es nulo y produce un error.

Funciones de afirmación y error

Para manejar errores, a menudo usamos dos funciones: assert y error. A continuación se muestra un ejemplo sencillo.

local function add(a,b)
   assert(type(a) == "number", "a is not a number")
   assert(type(b) == "number", "b is not a number")
   return a+b
end

add(10)

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado de error.

lua: test2.lua:3: b is not a number
stack traceback:
	[C]: in function 'assert'
	test2.lua:3: in function 'add'
	test2.lua:6: in main chunk
	[C]: ?

los error (message [, level])termina la última función protegida llamada y devuelve el mensaje como mensaje de error. Este error de función nunca vuelve. Por lo general, error agrega información sobre la posición del error al principio del mensaje. El argumento de nivel especifica cómo obtener la posición del error. Con el nivel 1 (predeterminado), la posición de error es donde se llamó a la función de error. El nivel 2 señala el error al lugar donde se llamó a la función que llamó al error; y así. Pasar un nivel 0 evita la adición de información de posición de error al mensaje.

pcall y xpcall

En la programación de Lua, para evitar lanzar estos errores y manejarlos, necesitamos usar las funciones pcall o xpcall.

los pcall (f, arg1, ...)función llama a la función solicitada en modo protegido. Si ocurre algún error en la función f, no arroja un error. Simplemente devuelve el estado de error. A continuación se muestra un ejemplo sencillo con pcall.

function myfunction ()
   n = n/nil
end

if pcall(myfunction) then
   print("Success")
else
	print("Failure")
end

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

Failure

los xpcall (f, err)function llama a la función solicitada y también establece el controlador de errores. Ningún error dentro de f no se propaga; en su lugar, xpcall detecta el error, llama a la función err con el objeto de error original y devuelve un código de estado.

A continuación se muestra un ejemplo sencillo de xpcall.

function myfunction ()
   n = n/nil
end

function myerrorhandler( err )
   print( "ERROR:", err )
end

status = xpcall( myfunction, myerrorhandler )
print( status)

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

ERROR:	test2.lua:2: attempt to perform arithmetic on global 'n' (a nil value)
false

Como programador, es muy importante asegurarse de que se ocupa del manejo adecuado de los errores en los programas que escribe. El uso de la gestión de errores puede garantizar que las condiciones inesperadas más allá de las condiciones límite se manejen sin molestar al usuario del programa.

Lua proporciona una biblioteca de depuración, que proporciona todas las funciones primitivas para que creemos nuestro propio depurador. Aunque no hay un depurador de Lua incorporado, tenemos muchos depuradores para Lua, creados por varios desarrolladores, muchos de los cuales son de código abierto.

Las funciones disponibles en la biblioteca de depuración de Lua se enumeran en la siguiente tabla junto con sus usos.

No Señor. Método y propósito
1

debug()

Ingresa al modo interactivo para depuración, que permanece activo hasta que escribimos solo cont en una línea y presionamos enter. El usuario puede inspeccionar variables durante este modo utilizando otras funciones.

2

getfenv(object)

Devuelve el entorno del objeto.

3

gethook(optional thread)

Devuelve la configuración de gancho actual del hilo, como tres valores: la función de gancho actual, la máscara de gancho actual y el recuento de gancho actual.

4

getinfo(optional thread, function or stack level, optional flag)

Devuelve una tabla con información sobre una función. Puede dar la función directamente, o puede dar un número como el valor de la función, lo que significa que la función que se ejecuta en el nivel de función de la pila de llamadas del subproceso dado - el nivel 0 es la función actual (getinfo en sí); el nivel 1 es la función que se llama getinfo; y así. Si la función es un número mayor que el número de funciones activas, entonces getinfo devuelve nil.

5

getlocal(optional thread, stack level, local index)

Devuelve el nombre y el valor de la variable local con índice local de la función en el nivel de la pila. Devuelve nulo si no hay una variable local con el índice dado, y genera un error cuando se llama con un nivel fuera de rango.

6

getmetatable(value)

Devuelve la metatabla del objeto dado o nil si no tiene una metatabla.

7

getregistry()

Devuelve la tabla de registro, una tabla predefinida que puede ser utilizada por cualquier código C para almacenar cualquier valor de Lua que necesite almacenar.

8

getupvalue(function, upvalue index)

Esta función devuelve el nombre y el valor del upvalue con index up de la función func. La función devuelve nil si no hay ningún valor al alza con el índice dado.

9

setfenv(function or thread or userdata, environment table)

Establece el entorno del objeto dado en la tabla dada. Devuelve el objeto.

10

sethook(optional thread, hook function, hook mask string with "c" and/or "r" and/or "l", optional instruction count)

Establece la función dada como un gancho. La máscara de cadena y el recuento de números describen cuándo se llamará al gancho. Aquí, c, r y l se llaman cada vez que Lua llama, regresa e ingresa cada línea de código en una función, respectivamente.

11

setlocal(optional thread, stack level, local index, value)

Asigna el valor a la variable local con índice local de la función a nivel de la pila. La función devuelve nil si no hay una variable local con el índice dado y genera un error cuando se llama con un nivel fuera de rango. De lo contrario, devuelve el nombre de la variable local.

12

setmetatable(value, metatable)

Establece la metatabla para el objeto dado en la tabla dada (que puede ser nula).

13

setupvalue(function, upvalue index, value)

Esta función asigna el valor al upvalue con index up de la función func. La función devuelve nil si no hay ningún valor al alza con el índice dado. De lo contrario, devuelve el nombre del upvalue.

14

traceback(optional thread, optional message string, optional level argument)

Genera un mensaje de error extendido con seguimiento.

La lista anterior es la lista completa de funciones de depuración en Lua y, a menudo, usamos una biblioteca que usa las funciones anteriores y proporciona una depuración más fácil. Usar estas funciones y crear nuestro propio depurador es bastante complicado y no es preferible. De todos modos, veremos un ejemplo de uso simple de funciones de depuración.

function myfunction ()
   print(debug.traceback("Stack trace"))
   print(debug.getinfo(1))
   print("Stack trace end")

   return 10
end

myfunction ()
print(debug.getinfo(1))

Cuando ejecutamos el programa anterior, obtendremos el seguimiento de la pila como se muestra a continuación.

Stack trace
stack traceback:
	test2.lua:2: in function 'myfunction'
	test2.lua:8: in main chunk
	[C]: ?
table: 0054C6C8
Stack trace end

En el programa de muestra anterior, el seguimiento de la pila se imprime utilizando la función debug.trace disponible en la biblioteca de depuración. El debug.getinfo obtiene la tabla actual de la función.

Depuración - Ejemplo

A menudo necesitamos conocer las variables locales de una función para depurar. Para ese propósito, podemos usar getupvalue y para establecer estas variables locales, usamos setupvalue. A continuación se muestra un ejemplo sencillo de esto.

function newCounter ()
   local n = 0
   local k = 0
	
   return function ()
      k = n
      n = n + 1
      return n
   end
	
end

counter = newCounter ()

print(counter())
print(counter())

local i = 1

repeat
   name, val = debug.getupvalue(counter, i)
	
   if name then
      print ("index", i, name, "=", val)
		
      if(name == "n") then
         debug.setupvalue (counter,2,10)
      end
		
      i = i + 1
   end -- if
	
until not name

print(counter())

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

1
2
index	1	k	=	1
index	2	n	=	2
11

En este ejemplo, el contador se actualiza en uno cada vez que se llama. Podemos ver el estado actual de la variable local usando la función getupvalue. Luego establecemos la variable local en un nuevo valor. Aquí, n es 2 antes de que se llame a la operación de conjunto. Usando la función setupvalue, se actualiza a 10. Ahora, cuando llamemos a la función de contador, devolverá 11 en lugar de 3.

Tipos de depuración

  • Depuración de línea de comando
  • Depuración gráfica

Depuración de línea de comandos

La depuración de la línea de comandos es el tipo de depuración que utiliza la línea de comandos para depurar con la ayuda de comandos y declaraciones de impresión. Hay muchos depuradores de línea de comandos disponibles para Lua, algunos de los cuales se enumeran a continuación.

  • RemDebug- RemDebug es un depurador remoto para Lua 5.0 y 5.1. Le permite controlar la ejecución de otro programa Lua de forma remota, estableciendo puntos de interrupción e inspeccionando el estado actual del programa. RemDebug también puede depurar scripts CGILua.

  • clidebugger- Un depurador de interfaz de línea de comandos simple para Lua 5.1 escrito en Lua puro. No depende de nada más que de las bibliotecas estándar de Lua 5.1. Se inspiró en RemDebug pero no tiene sus instalaciones remotas.

  • ctrace - Una herramienta para rastrear llamadas API de Lua.

  • xdbLua - Un depurador de línea de comandos de Lua simple para la plataforma Windows.

  • LuaInterface - Debugger- Este proyecto es una extensión de depuración para LuaInterface. Eleva la interfaz de depuración de Lua incorporada a un nivel superior. La interacción con el depurador se realiza mediante eventos y llamadas a métodos.

  • Rldb- Este es un depurador remoto de Lua a través de socket, disponible tanto en Windows como en Linux. Puede ofrecerle muchas más funciones que cualquier otra existente.

  • ModDebug - Esto permite controlar la ejecución de otro programa Lua de forma remota, establecer puntos de interrupción e inspeccionar el estado actual del programa.

Depuración gráfica

La depuración gráfica está disponible con la ayuda de IDE, donde se le proporciona la depuración visual de varios estados, como valores de variables, seguimiento de pila y otra información relacionada. Hay una representación visual y un control paso a paso de la ejecución con la ayuda de puntos de interrupción, paso a paso, paso a paso y otros botones en el IDE.

Hay varios depuradores gráficos para Lua e incluye lo siguiente.

  • SciTE - El IDE de Windows predeterminado para Lua proporciona múltiples funciones de depuración como puntos de interrupción, paso, paso a paso, paso a paso, variables de observación, etc.

  • Decoda - Este es un depurador gráfico con soporte de depuración remota.

  • ZeroBrane Studio- Lua IDE con depurador remoto integrado, vista de pila, vista de reloj, consola remota, analizador estático y más. Funciona con LuaJIT, Love2d, Moai y otros motores Lua; Windows, OSX y Linux. Fuente abierta.

  • akdebugger - Plugin de depurador y editor Lua para Eclipse.

  • luaedit - Esto incluye depuración remota, depuración local, resaltado de sintaxis, lista de propuestas de finalización, motor de propuesta de parámetros, gestión avanzada de puntos de interrupción (incluido el sistema de condiciones en puntos de interrupción y recuento de aciertos), listado de funciones, listado de variables globales y locales, relojes, gestión orientada a soluciones.

Lua usa la administración automática de memoria que usa la recolección de basura basada en ciertos algoritmos que están incorporados en Lua. Como resultado de la gestión automática de la memoria, como desarrollador:

  • No hay necesidad de preocuparse por asignar memoria a los objetos.
  • No es necesario liberarlos cuando ya no los necesite, excepto para establecerlo en cero.

Lua usa un recolector de basura que se ejecuta de vez en cuando para recolectar objetos muertos cuando ya no son accesibles desde el programa Lua.

Todos los objetos, incluidas tablas, datos de usuario, funciones, subprocesos, cadenas, etc., están sujetos a la gestión automática de la memoria. Lua usa un recolector de marca y barrido incremental que usa dos números para controlar sus ciclos de recolección de basura, a sabergarbage collector pause y garbage collector step multiplier. Estos valores están en porcentaje y el valor de 100 a menudo es igual a 1 internamente.

Pausa del recolector de basura

La pausa del recolector de basura se usa para controlar cuánto tiempo debe esperar el recolector de basura, antes; es llamado nuevamente por la administración automática de memoria de Lua. Los valores inferiores a 100 significarían que Lua no esperará al próximo ciclo. De manera similar, valores más altos de este valor darían como resultado que el recolector de basura fuera lento y menos agresivo por naturaleza. Un valor de 200 significa que el colector espera que la memoria total en uso se duplique antes de comenzar un nuevo ciclo. Por lo tanto, dependiendo de la naturaleza y la velocidad de la aplicación, puede ser necesario modificar este valor para obtener el mejor rendimiento en las aplicaciones Lua.

Multiplicador de pasos del recolector de basura

Este multiplicador de pasos controla la velocidad relativa del recolector de basura a la de la asignación de memoria en el programa Lua. Los valores de paso más grandes harán que el recolector de basura sea más agresivo y también aumentará el tamaño de paso de cada paso incremental de la recolección de basura. Los valores inferiores a 100 a menudo pueden hacer que el recolector de basura no complete su ciclo y, en general, no se prefiere. El valor predeterminado es 200, lo que significa que el recolector de basura se ejecuta al doble de la velocidad de asignación de memoria.

Funciones del recolector de basura

Como desarrolladores, tenemos cierto control sobre la gestión automática de la memoria en Lua. Para ello, disponemos de los siguientes métodos.

  • collectgarbage("collect") - Ejecuta un ciclo completo de recolección de basura.

  • collectgarbage("count") - Devuelve la cantidad de memoria utilizada actualmente por el programa en Kilobytes.

  • collectgarbage("restart") - Si el recolector de basura se ha detenido, lo reinicia.

  • collectgarbage("setpause")- Establece el valor dado como segundo parámetro dividido por 100 para la variable de pausa del recolector de basura. Sus usos son los discutidos un poco más arriba.

  • collectgarbage("setstepmul")- Establece el valor dado como segundo parámetro dividido por 100 para la variable multiplicadora del paso de basura. Sus usos son los discutidos un poco más arriba.

  • collectgarbage("step")- Ejecuta un paso de recolección de basura. Cuanto mayor sea el segundo argumento, mayor será este paso. La recolección de basura devolverá verdadero si el paso activado fue el último paso de un ciclo de recolección de basura.

  • collectgarbage("stop") - Detiene el recolector de basura si se está ejecutando.

A continuación, se muestra un ejemplo sencillo que utiliza el ejemplo del recolector de basura.

mytable = {"apple", "orange", "banana"}

print(collectgarbage("count"))

mytable = nil

print(collectgarbage("count"))

print(collectgarbage("collect"))

print(collectgarbage("count"))

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado. Tenga en cuenta que este resultado variará debido a la diferencia en el tipo de sistema operativo y también a la función de gestión automática de memoria de Lua.

23.1455078125   149
23.2880859375   295
0
22.37109375     380

Puede ver en el programa anterior, una vez que se realiza la recolección de basura, se reduce la memoria utilizada. Pero no es obligatorio llamar a esto. Incluso si no los llamamos, el intérprete de Lua lo ejecutará automáticamente en una etapa posterior después del período predefinido.

Obviamente, podemos cambiar el comportamiento del recolector de basura usando estas funciones si es necesario. Estas funciones proporcionan un poco de capacidad adicional para que el desarrollador maneje situaciones complejas. Dependiendo del tipo de memoria que necesite el programa, es posible que utilice esta función o no. Pero es muy útil conocer el uso de memoria en las aplicaciones y comprobarlo durante la propia programación para evitar resultados no deseados tras la implementación.

Introducción a la programación orientada a objetos

La programación orientada a objetos (OOP), es una de las técnicas de programación más utilizadas en la era moderna de la programación. Hay una serie de lenguajes de programación que admiten OOP que incluyen,

  • C++
  • Java
  • Objective-C
  • Smalltalk
  • C#
  • Ruby

Características de OOP

  • Class - Una clase es una plantilla extensible para crear objetos, que proporciona valores iniciales para el estado (variables miembro) e implementaciones de comportamiento.

  • Objects - Es una instancia de clase y tiene una memoria separada asignada para sí mismo.

  • Inheritance - Es un concepto por el cual las variables y funciones de una clase son heredadas por otra clase.

  • Encapsulation- Es el proceso de combinar los datos y funciones dentro de una clase. Se puede acceder a los datos fuera de la clase con la ayuda de funciones. También se conoce como abstracción de datos.

POO en Lua

Puede implementar la orientación a objetos en Lua con la ayuda de tablas y funciones de primera clase de Lua. Al colocar funciones y datos relacionados en una tabla, se forma un objeto. La herencia se puede implementar con la ayuda de metatablas, proporcionando un mecanismo de búsqueda para funciones (métodos) y campos inexistentes en los objetos principales.

Las tablas en Lua tienen características de objeto como estado e identidad que es independiente de sus valores. Dos objetos (tablas) con el mismo valor son objetos diferentes, mientras que un objeto puede tener valores diferentes en momentos diferentes, pero siempre es el mismo objeto. Como los objetos, las tablas tienen un ciclo de vida que es independiente de quién las creó o dónde fueron creadas.

Un ejemplo del mundo real

El concepto de orientación a objetos se usa ampliamente, pero es necesario comprenderlo claramente para obtener el máximo beneficio.

Consideremos un ejemplo matemático simple. A menudo nos encontramos con situaciones en las que trabajamos en diferentes formas como círculo, rectángulo y cuadrado.

Las formas pueden tener un área de propiedad común. Entonces, podemos extender otras formas desde la forma del objeto base con el área de propiedad común. Cada una de las formas puede tener sus propias propiedades y funciones, como un rectángulo puede tener propiedades length, width, area como propiedades y printArea y calculateArea como funciones.

Crear una clase simple

A continuación se muestra una implementación de clase simple para un rectángulo con tres propiedades de área, longitud y amplitud. También tiene una función printArea para imprimir el área calculada.

-- Meta class
Rectangle = {area = 0, length = 0, breadth = 0}

-- Derived class method new

function Rectangle:new (o,length,breadth)
   o = o or {}
   setmetatable(o, self)
   self.__index = self
   self.length = length or 0
   self.breadth = breadth or 0
   self.area = length*breadth;
   return o
end

-- Derived class method printArea

function Rectangle:printArea ()
   print("The area of Rectangle is ",self.area)
end

Crear un objeto

La creación de un objeto es el proceso de asignación de memoria para la instancia de la clase. Cada uno de los objetos tiene su propia memoria y comparte los datos de clase comunes.

r = Rectangle:new(nil,10,20)

Accediendo a Propiedades

Podemos acceder a las propiedades en la clase usando el operador de punto como se muestra a continuación:

print(r.length)

Acceso a la función de miembro

Puede acceder a una función miembro utilizando el operador de dos puntos con el objeto como se muestra a continuación:

r:printArea()

Se asigna la memoria y se establecen los valores iniciales. El proceso de inicialización se puede comparar con constructores en otros lenguajes orientados a objetos. No es más que una función que permite configurar valores como se muestra arriba.

Ejemplo completo

Veamos un ejemplo completo usando la orientación a objetos en Lua.

-- Meta class
Shape = {area = 0}

-- Base class method new

function Shape:new (o,side)
   o = o or {}
   setmetatable(o, self)
   self.__index = self
   side = side or 0
   self.area = side*side;
   return o
end

-- Base class method printArea

function Shape:printArea ()
   print("The area is ",self.area)
end

-- Creating an object
myshape = Shape:new(nil,10)

myshape:printArea()

Cuando ejecute el programa anterior, obtendrá el siguiente resultado.

The area is 	100

Herencia en Lua

La herencia es el proceso de extender objetos básicos simples como formas a rectángulos, cuadrados, etc. A menudo se utiliza en el mundo real para compartir y ampliar las propiedades y funciones básicas.

Veamos una extensión de clase simple. Tenemos una clase como se muestra a continuación.

-- Meta class
Shape = {area = 0}

-- Base class method new

function Shape:new (o,side)
   o = o or {}
   setmetatable(o, self)
   self.__index = self
   side = side or 0
   self.area = side*side;
   return o
end

-- Base class method printArea

function Shape:printArea ()
   print("The area is ",self.area)
end

Podemos extender la forma a una clase cuadrada como se muestra a continuación.

Square = Shape:new()

-- Derived class method new

function Square:new (o,side)
   o = o or Shape:new(o,side)
   setmetatable(o, self)
   self.__index = self
   return o
end

Funciones básicas anuladas

Podemos anular las funciones de la clase base que es en lugar de usar la función en la clase base, la clase derivada puede tener su propia implementación como se muestra a continuación:

-- Derived class method printArea

function Square:printArea ()
   print("The area of square is ",self.area)
end

Ejemplo completo de herencia

Podemos extender la implementación de la clase simple en Lua como se muestra arriba con la ayuda de otro método nuevo con la ayuda de metatablas. Todas las variables miembro y funciones de la clase base se conservan en la clase derivada.

-- Meta class
Shape = {area = 0}

-- Base class method new

function Shape:new (o,side)
   o = o or {}
   setmetatable(o, self)
   self.__index = self
   side = side or 0
   self.area = side*side;
   return o
end

-- Base class method printArea

function Shape:printArea ()
   print("The area is ",self.area)
end

-- Creating an object
myshape = Shape:new(nil,10)
myshape:printArea()

Square = Shape:new()

-- Derived class method new

function Square:new (o,side)
   o = o or Shape:new(o,side)
   setmetatable(o, self)
   self.__index = self
   return o
end

-- Derived class method printArea

function Square:printArea ()
   print("The area of square is ",self.area)
end

-- Creating an object
mysquare = Square:new(nil,10)
mysquare:printArea()

Rectangle = Shape:new()

-- Derived class method new

function Rectangle:new (o,length,breadth)
   o = o or Shape:new(o)
   setmetatable(o, self)
   self.__index = self
   self.area = length * breadth
   return o
end

-- Derived class method printArea

function Rectangle:printArea ()
    print("The area of Rectangle is ",self.area)
end

-- Creating an object

myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado:

The area is 	100
The area of square is 	100
The area of Rectangle is 	200

En el ejemplo anterior, hemos creado dos clases derivadas: Rectángulo y Cuadrado a partir de la clase base Cuadrado. Es posible anular las funciones de la clase base en la clase derivada. En este ejemplo, la clase derivada anula la función printArea.

Lua es un lenguaje muy flexible y a menudo se usa en múltiples plataformas, incluidas las aplicaciones web. La comunidad de Kepler que se formó en 2004 para proporcionar componentes web de código abierto en Lua.

Aunque hay otros marcos web que utilizan Lua que se han desarrollado, nos centraremos principalmente en los componentes proporcionados por la comunidad de Kepler.

Aplicaciones y marcos

  • Orbit es un marco web MVC para Lua, basado en WSAPI.

  • WSAPI es la API que abstrae el servidor de alojamiento web de las aplicaciones web de Lua y es la base de muchos proyectos.

  • Xavante es un servidor web Lua que ofrece una interfaz WSAPI.

  • Sputnik es un wiki / CMS desarrollado sobre WSAPI en Kepler Project que se utiliza para el humor y el entretenimiento.

  • CGILuaofrece creación de páginas web LuaPages y LuaScripts, basadas en WSAPI pero que ya no son compatibles. En su lugar, utilice Orbit, Sputnik o WSAPI.

En este tutorial, intentaremos hacerle comprender lo que puede hacer Lua y para saber más sobre su instalación y uso, consulte kepler en el sitio web.

Orbita

Orbit es un marco web MVC para Lua. Abandona por completo el modelo CGILua de "scripts" en favor de las aplicaciones, donde cada aplicación de Orbit puede caber en un solo archivo, pero puede dividirlo en varios archivos si lo desea.

Todas las aplicaciones de Orbit siguen el protocolo WSAPI, por lo que actualmente funcionan con Xavante, CGI y Fastcgi. Incluye un lanzador que facilita el lanzamiento de una instancia de Xavante para su desarrollo.

La forma más sencilla de instalar Orbit es utilizando LuaRocks. Luarocks install orbit es el comando para la instalación. Para ello, primero debe instalar LuaRocks .

Si no ha instalado todas las dependencias, estos son los pasos a seguir para configurar Orbit en un entorno Unix / Linux.

Instalación de Apache

Conéctese a su servidor. Instale Apache2, sus módulos de soporte y habilite los módulos de Apache2 requeridos usando -

$ sudo apt-get install apache2 libapache2-mod-fcgid libfcgi-dev build-essential $ sudo a2enmod rewrite
$ sudo a2enmod fcgid $ sudo /etc/init.d/apache2 force-reload

Instalar LuaRocks

$ sudo apt-get install luarocks

Instale WSAPI, FCGI, Orbit y Xavante

$ sudo luarocks install orbit
$ sudo luarocks install wsapi-xavante $ sudo luarocks install wsapi-fcgi

Configuración de Apache2

$ sudo raj /etc/apache2/sites-available/default

Agregue la siguiente sección debajo de la sección <Directory / var / www /> del archivo de configuración. Si esta sección tiene un 'AllowOverride None', entonces debe cambiar 'None' a 'All' para que el archivo .htaccess pueda anular la configuración localmente.

<IfModule mod_fcgid.c>

   AddHandler fcgid-script .lua
   AddHandler fcgid-script .ws
   AddHandler fcgid-script .op
	
   FCGIWrapper "/usr/local/bin/wsapi.fcgi" .ws
   FCGIWrapper "/usr/local/bin/wsapi.fcgi" .lua
   FCGIWrapper "/usr/local/bin/op.fcgi" .op
	
   #FCGIServer "/usr/local/bin/wsapi.fcgi" -idle-timeout 60 -processes 1
   #IdleTimeout 60
   #ProcessLifeTime 60
	
</IfModule>

Reinicie el servidor para asegurarse de que los cambios realizados entren en vigor.

Para habilitar su aplicación, debe agregar + ExecCGI a un archivo .htaccess en la raíz de su aplicación Orbit, en este caso, / var / www.

Options +ExecCGI
DirectoryIndex index.ws

Ejemplo simple: órbita

#!/usr/bin/env index.lua

-- index.lua
require"orbit"

-- declaration
module("myorbit", package.seeall, orbit.new)

-- handler

function index(web)
   return my_home_page()
end

-- dispatch
myorbit:dispatch_get(index, "/", "/index")

-- Sample page

function my_home_page()

   return [[
      <head></head>
      <html>
         <h2>First Page</h2>
      </html>
   ]]
	
end

Ahora, debería poder iniciar su navegador web. Vaya a http: // localhost: 8080 / y debería ver el siguiente resultado:

First Page

Orbit ofrece otra opción, es decir, el código Lua puede generar html.

#!/usr/bin/env index.lua

-- index.lua
require"orbit"

function generate()
   return html {
      head{title "HTML Example"},
		
      body{
         h2{"Here we go again!"}
      }
   }
end

orbit.htmlify(generate)

print(generate())

Crear formularios

A continuación se muestra un ejemplo de formulario simple:

#!/usr/bin/env index.lua
require"orbit"

function wrap (inner)
   return html{ head(), body(inner) }
end

function test ()
   return wrap(form (H'table' {
      tr{td"First name",td( input{type = 'text', name='first'})},
      tr{td"Second name",td(input{type = 'text', name='second'})},
      tr{ td(input{type = 'submit', value = 'Submit!'}),
         td(input{type = 'submit',value = 'Cancel'})
      },
   }))
end

orbit.htmlify(wrap,test)

print(test())

WSAPI

Como se mencionó anteriormente, WSAPI actúa como base para muchos proyectos y tiene múltiples características integradas. Puede utilizar WSAPI y admitir las siguientes plataformas,

  • Windows
  • Sistemas basados ​​en UNIX

Los servidores e interfaces admitidos por WSAPI incluyen,

  • CGI
  • FastCGI
  • Xavante

WSAPI proporciona una serie de bibliotecas, lo que nos facilita la programación web con Lua. Algunas de las funciones admitidas en Lua incluyen,

  • Procesamiento de solicitudes
  • Almacenamiento en búfer de salida
  • Authentication
  • Cargas de archivos
  • Solicitar aislamiento
  • Multiplexing

A continuación se muestra un ejemplo simple de WSAPI:

#!/usr/bin/env wsapi.cgi

module(..., package.seeall)
function run(wsapi_env)
   local headers = { ["Content-type"] = "text/html" }
   
   local function hello_text()
      coroutine.yield("<html><body>")
      coroutine.yield("<p&gtHello Wsapi!</p>")
      coroutine.yield("<p&gtPATH_INFO: " .. wsapi_env.PATH_INFO .. "</p>")
      coroutine.yield("<p&gtSCRIPT_NAME: " .. wsapi_env.SCRIPT_NAME .. "</p>")
      coroutine.yield("</body></html>")
   end

   return 200, headers, coroutine.wrap(hello_text)
end

Puede ver en el código anterior que se forma y se devuelve una página html simple. Puede ver el uso de corrutinas que hace posible devolver instrucción por instrucción a la función de llamada. Finalmente, se devuelve el código de estado html (200), los encabezados y la página html.

Xavante

Xavante es un servidor web Lua HTTP 1.1 que utiliza una arquitectura modular basada en manejadores mapeados por URI. Xavante ofrece actualmente,

  • Manejador de archivos
  • Controlador de redireccionamiento
  • Controlador WSAPI

El controlador de archivos se utiliza para archivos generales. El manejador de redireccionamiento habilita la reasignación de URI y el manejador WSAPI para administrar aplicaciones WSAPI.

A continuación se muestra un ejemplo sencillo.

require "xavante.filehandler"
require "xavante.cgiluahandler"
require "xavante.redirecthandler"

-- Define here where Xavante HTTP documents scripts are located
local webDir = XAVANTE_WEB

local simplerules = {

   { -- URI remapping example
      match = "^[^%./]*/$",
      with = xavante.redirecthandler,
      params = {"index.lp"}
   }, 

   { -- cgiluahandler example
      match = {"%.lp$", "%.lp/.*$", "%.lua$", "%.lua/.*$" },
      with = xavante.cgiluahandler.makeHandler (webDir)
   },
    
   { -- filehandler example
      match = ".",
      with = xavante.filehandler,
      params = {baseDir = webDir}
   },
} 

xavante.HTTP{
   server = {host = "*", port = 8080},
    
   defaultHost = {
      rules = simplerules
   },
}

Para usar hosts virtuales con Xavante, la llamada a xavante.HTTP se cambiaría a algo como lo siguiente:

xavante.HTTP{
   server = {host = "*", port = 8080},
    
   defaultHost = {},
    
   virtualhosts = {
      ["www.sitename.com"] = simplerules
   }
}

Componentes web de Lua

  • Copas, un despachador basado en corrutinas que pueden utilizar los servidores TCP / IP.

  • Cosmo, un motor de "plantillas seguras" que protege su aplicación de código arbitrario en las plantillas.

  • Coxpcall encapsula pcall y xpcall nativos de Lua con otros compatibles con la rutina.

  • LuaFileSystem, una forma portátil de acceder a la estructura de directorio subyacente y los atributos de archivo.

  • Rings, una biblioteca que proporciona una forma de crear nuevos estados Lua desde dentro de Lua.

Nota final

Hay tantos marcos y componentes web basados ​​en Lua disponibles para nosotros y, en función de la necesidad, se puede elegir. Hay otros marcos web disponibles que incluyen lo siguiente:

  • Moonstalkpermite el desarrollo y alojamiento eficiente de proyectos basados ​​en la web generados dinámicamente construidos con el lenguaje Lua; desde páginas básicas hasta aplicaciones complejas.

  • Lapis, un marco para crear aplicaciones web usando MoonScript (o Lua) que se ejecuta dentro de una versión personalizada de Nginx llamada OpenResty.

  • Lua Server Pages, un complemento de motor de secuencias de comandos de Lua que supera cualquier otro enfoque de desarrollo web integrado, ofrece un atajo espectacular a las páginas del servidor C tradicionales.

Estos marcos web pueden aprovechar sus aplicaciones web y ayudarlo a realizar operaciones poderosas.

Para operaciones de datos simples, podemos usar archivos, pero, a veces, estas operaciones de archivos pueden no ser eficientes, escalables y poderosas. Para este propósito, a menudo podemos cambiar al uso de bases de datos. LuaSQL es una interfaz simple de Lua a varios sistemas de administración de bases de datos. LuaSQL es la biblioteca que brinda soporte para diferentes tipos de SQL. Esto incluye,

  • SQLite
  • Mysql
  • ODBC

En este tutorial, cubriremos el manejo de bases de datos de MySQL y SQLite en Lua. Esto utiliza una interfaz genérica para ambos y también debería ser posible portar esta implementación a otros tipos de bases de datos. Primero veamos cómo puede realizar las operaciones en MySQL.

Configuración de base de datos de MySQL

Para que los siguientes ejemplos funcionen como se esperaba, necesitamos la configuración inicial de la base de datos. Los supuestos se enumeran a continuación.

  • Ha instalado y configurado MySQL con el usuario predeterminado como root y la contraseña como '123456'.

  • Ha creado una prueba de base de datos.

  • Ha seguido el tutorial de MySQL para comprender los conceptos básicos de MySQL.

Importando MySQL

Podemos usar un simple require declaración para importar la biblioteca sqlite asumiendo que su implementación de Lua se realizó correctamente.

mysql = require "luasql.mysql"

La variable mysql proporcionará acceso a las funciones haciendo referencia a la tabla principal de mysql.

Configurar conexión

Podemos configurar la conexión iniciando un entorno MySQL y luego creando una conexión para el entorno. Se muestra a continuación.

local env  = mysql.mysql()
local conn = env:connect('test','root','123456')

La conexión anterior se conectará a un archivo MySQL existente y establecerá la conexión con el archivo recién creado.

Ejecutar función

Hay una función de ejecución simple disponible con la conexión que nos ayudará a hacer todas las operaciones de la base de datos desde crear, insertar, eliminar, actualizar, etc. La sintaxis se muestra a continuación:

conn:execute([[ 'MySQLSTATEMENT' ]])

En la sintaxis anterior, debemos asegurarnos de que conn esté abierta y que exista una conexión MySQL y reemplazar 'MySQLSTATEMENT' con la declaración correcta.

Ejemplo de creación de tabla

A continuación se muestra un ejemplo simple de creación de tabla. Crea una tabla con dos parámetros id de tipo integer y nombre de tipo varchar.

mysql = require "luasql.mysql"

local env  = mysql.mysql()
local conn = env:connect('test','root','123456')

print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample2 (id INTEGER, name TEXT);]])
print(status,errorString )

Cuando ejecute el programa anterior, se creará una tabla llamada muestra con dos columnas, a saber, id y nombre.

MySQL environment (004BB178)	MySQL connection (004BE3C8)
0	nil

En caso de que haya algún error, se le devolverá una declaración de error en lugar de nil. A continuación se muestra una simple declaración de error.

LuaSQL: Error executing query. MySQL: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"id INTEGER, name TEXT)' at line 1

Insertar ejemplo de declaración

A continuación se muestra una declaración de inserción para MySQL.

conn:execute([[INSERT INTO sample values('11','Raj')]])

Ejemplo de declaración de actualización

A continuación, se muestra una declaración de actualización para MySQL.

conn:execute([[UPDATE sample3 SET name='John' where id ='12']])

Ejemplo de declaración de eliminación

A continuación se muestra una declaración de eliminación para MySQL.

conn:execute([[DELETE from sample3 where id ='12']])

Seleccionar ejemplo de declaración

En lo que respecta a la declaración de selección, necesitamos recorrer cada una de las filas y extraer los datos requeridos. A continuación se muestra una declaración de selección simple.

cursor,errorString = conn:execute([[select * from sample]])
row = cursor:fetch ({}, "a")

while row do
   print(string.format("Id: %s, Name: %s", row.id, row.name))
   -- reusing the table of results
   row = cursor:fetch (row, "a")
end

En el código anterior, conn es una conexión MySQL abierta. Con la ayuda del cursor devuelto por la instrucción de ejecución, puede recorrer la respuesta de la tabla y obtener los datos de selección necesarios.

Un ejemplo completo

A continuación se proporciona un ejemplo completo que incluye todas las declaraciones anteriores.

mysql = require "luasql.mysql"

local env  = mysql.mysql()
local conn = env:connect('test','root','123456')
print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample3 (id INTEGER, name TEXT)]])
print(status,errorString )

status,errorString = conn:execute([[INSERT INTO sample3 values('12','Raj')]])
print(status,errorString )

cursor,errorString = conn:execute([[select * from sample3]])
print(cursor,errorString)

row = cursor:fetch ({}, "a")

while row do
   print(string.format("Id: %s, Name: %s", row.id, row.name))
   row = cursor:fetch (row, "a")
end

-- close everything
cursor:close()
conn:close()
env:close()

Cuando ejecute el programa anterior, obtendrá el siguiente resultado.

MySQL environment (0037B178)	MySQL connection (0037EBA8)
0	nil
1	nil
MySQL cursor (003778A8)	nil
Id: 12, Name: Raj

Realización de transacciones

Las transacciones son un mecanismo que garantiza la coherencia de los datos. Las transacciones deben tener las siguientes cuatro propiedades:

  • Atomicity - O se completa una transacción o no ocurre nada.

  • Consistency - Una transacción debe comenzar en un estado consistente y dejar el sistema en un estado consistente.

  • Isolation - Los resultados intermedios de una transacción no son visibles fuera de la transacción actual.

  • Durability - Una vez que se comprometió una transacción, los efectos son persistentes, incluso después de una falla del sistema.

La transacción comienza con INICIAR TRANSACCIÓN; y termina con una declaración de compromiso o reversión.

Iniciar transacción

Para iniciar una transacción, necesitamos ejecutar la siguiente declaración en Lua, asumiendo que conn es una conexión MySQL abierta.

conn:execute([[START TRANSACTION;]])

Transacción de reversión

Necesitamos ejecutar la siguiente declaración para revertir los cambios realizados después de que se ejecuta la transacción de inicio.

conn:execute([[ROLLBACK;]])

Confirmar transacción

Necesitamos ejecutar la siguiente declaración para confirmar los cambios realizados después de que se ejecute la transacción de inicio.

conn:execute([[COMMIT;]])

Hemos conocido MySQL en la sección anterior y la siguiente explica las operaciones básicas de SQL. Recuerde las transacciones, aunque no se explican nuevamente para SQLite3, pero las mismas declaraciones deberían funcionar para SQLite3 también.

Importando SQLite

Podemos usar una simple instrucción require para importar la biblioteca SQLite asumiendo que su implementación de Lua se realizó correctamente. Durante la instalación, una carpeta libsql que contiene los archivos relacionados con la base de datos.

sqlite3 = require "luasql.sqlite3"

La variable sqlite3 proporcionará acceso a las funciones haciendo referencia a la tabla principal sqlite3.

Configuración de la conexión

Podemos configurar la conexión iniciando un entorno SQLite y luego creando una conexión para el entorno. Se muestra a continuación.

local env  = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')

La conexión anterior se conectará a un archivo SQLite existente o creará un nuevo archivo SQLite y establecerá la conexión con el archivo recién creado.

Ejecutar función

Hay una función de ejecución simple disponible con la conexión que nos ayudará a hacer todas las operaciones de la base de datos desde crear, insertar, eliminar, actualizar, etc. La sintaxis se muestra a continuación:

conn:execute([[ 'SQLite3STATEMENT' ]])

En la sintaxis anterior, debemos asegurarnos de que conn esté abierto y que exista una conexión sqlite3 y reemplazar 'SQLite3STATEMENT' con la declaración correcta.

Ejemplo de creación de tabla

A continuación se muestra un ejemplo simple de creación de tabla. Crea una tabla con dos parámetros id de tipo integer y nombre de tipo varchar.

sqlite3 = require "luasql.sqlite3"

local env  = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')
print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample ('id' INTEGER, 'name' TEXT)]])
print(status,errorString )

Cuando ejecute el programa anterior, se creará una tabla llamada muestra con dos columnas, a saber, id y nombre.

SQLite3 environment (003EC918)	SQLite3 connection (00421F08)
0	nil

En caso de error, se le devolverá una declaración de error en lugar de nil. A continuación se muestra una simple declaración de error.

LuaSQL: unrecognized token: ""'id' INTEGER, 'name' TEXT)"

Insertar ejemplo de declaración

A continuación se muestra una declaración de inserción para SQLite.

conn:execute([[INSERT INTO sample values('11','Raj')]])

Seleccionar ejemplo de declaración

En lo que respecta a la declaración de selección, necesitamos recorrer cada una de las filas y extraer los datos requeridos. A continuación se muestra una declaración de selección simple.

cursor,errorString = conn:execute([[select * from sample]])
row = cursor:fetch ({}, "a")

while row do
   print(string.format("Id: %s, Name: %s", row.id, row.name))
   -- reusing the table of results
   row = cursor:fetch (row, "a")
end

En el código anterior, conn es una conexión sqlite3 abierta. Con la ayuda del cursor devuelto por la instrucción de ejecución, puede recorrer la respuesta de la tabla y obtener los datos de selección necesarios.

Un ejemplo completo

A continuación se proporciona un ejemplo completo que incluye todas las declaraciones anteriores.

sqlite3 = require "luasql.sqlite3"

local env  = sqlite3.sqlite3()
local conn = env:connect('mydb.sqlite')
print(env,conn)

status,errorString = conn:execute([[CREATE TABLE sample ('id' INTEGER, 'name' TEXT)]])
print(status,errorString )

status,errorString = conn:execute([[INSERT INTO sample values('1','Raj')]])
print(status,errorString )

cursor,errorString = conn:execute([[select * from sample]])
print(cursor,errorString)

row = cursor:fetch ({}, "a")

while row do
   print(string.format("Id: %s, Name: %s", row.id, row.name))
   row = cursor:fetch (row, "a")
end

-- close everything
cursor:close()
conn:close()
env:close()

Cuando ejecute el programa anterior, obtendrá el siguiente resultado.

SQLite3 environment (005EC918)	SQLite3 connection (005E77B0)
0	nil
1	nil
SQLite3 cursor (005E9200)	nil
Id: 1, Name: Raj

Podemos ejecutar todas las consultas disponibles con la ayuda de esta biblioteca libsql. Por lo tanto, no se detenga con estos ejemplos. Experimente varias declaraciones de consulta disponibles en MySQL, SQLite3 y otras bases de datos compatibles en Lua.

Lua se utiliza en muchos motores de juegos debido a su estructura de lenguaje y sintaxis simples. La función de recolección de basura suele ser bastante útil en juegos que consumen mucha memoria debido a los gráficos ricos que se utilizan. Algunos motores de juegos que usan Lua incluyen:

  • Corona SDK
  • Gideros Mobile
  • ShiVa3D
  • SDK de Moai
  • LOVE
  • CryEngine

Cada uno de estos motores de juego se basa en Lua y hay un rico conjunto de API disponible en cada uno de estos motores. Veremos brevemente las capacidades de cada uno.

Corona SDK

Corona SDK es un motor de juegos móviles multiplataforma que admite plataformas iPhone, iPad y Android. Existe una versión gratuita de Corona SDK que se puede utilizar para juegos pequeños con funciones limitadas. Puede actualizar a otras versiones cuando sea necesario.

Corona SDK proporciona una serie de características que incluyen lo siguiente:

  • API de manejo de física y colisiones
  • API web y de red
  • API de Game Network
  • API de anuncios
  • API de análisis
  • API de bases de datos y sistemas de archivos
  • API de cifrado y matemáticas
  • API de audio y medios

Es más fácil y rápido desarrollar una aplicación usando las API anteriores en lugar de usar las API nativas por separado para iOS y Android.

Gideros Mobile

Gideros proporciona el SDK multiplataforma para crear juegos para iOS y Android. Es de uso gratuito con un toque hecho con Gideros. Algunas de las ventajas sorprendentes de Gideoros incluyen las siguientes:

  • Development IDE - Proporciona su propio IDE que facilita el desarrollo de aplicaciones Gideros.

  • Instant testing- Mientras desarrolla su juego, puede probarlo en un dispositivo real a través de Wifi en solo 1 segundo. No necesita perder su tiempo con un proceso de exportación o implementación.

  • Plugins- Puede ampliar fácilmente el núcleo con complementos. Importe su código existente (C, C ++, Java u Obj-C), únalo a Lua e interpretelo directamente. Decenas de complementos de código abierto ya están desarrollados y listos para usar.

  • Clean OOP approach - Gideros proporciona su propio sistema de clases con todos los estándares básicos de programación orientada a objetos, lo que le permite escribir código limpio y reutilizable para cualquiera de sus juegos futuros.

  • Native speed - Desarrollado sobre C / C ++ y OpenGL, tu juego se ejecuta a velocidad nativa y utiliza completamente la potencia de las CPU y GPU que se encuentran debajo.

ShiVa3D

ShiVa3D es uno de los motores de juegos 3D que proporciona un editor gráfico diseñado para crear aplicaciones y videojuegos para la web, consolas y dispositivos móviles. Es compatible con múltiples plataformas que incluyen Windows, Mac, Linux, iOS, Android, BlackBerry, Palm OS, Wii y WebOS.

Algunas de las características principales incluyen

  • Complementos estándar
  • API de modificación de malla
  • IDE
  • Editor de animación, océano y terreno integrado
  • Soporte del motor de física ODE
  • Control total del mapa de luz
  • Vista previa en vivo de materiales, partículas, senderos y HUD
  • Soporte de formato de intercambio de Collada

La edición web de Shiva3d es completamente gratuita y otras ediciones tienes suscribirte.

SDK de Moai

Moai SDK es un motor de juegos móviles multiplataforma que admite plataformas iPhone, iPad y Android. La plataforma Moai inicialmente consistía en Moai SDK, un motor de juegos de código abierto, y Moai Cloud, una plataforma en la nube como servicio para el alojamiento y la implementación de servicios de juegos. Ahora Moai Cloud está apagado y solo está disponible el motor del juego.

Moai SDK se ejecuta en múltiples plataformas, incluidas iOS, Android, Chrome, Windows, Mac y Linux.

AMOR

LOVE es un marco que puedes usar para crear juegos en 2D. Es gratis y de código abierto. Es compatible con las plataformas Windows, Mac OS X y Linux.

Proporciona múltiples funciones que incluyen,

  • API de audio
  • API del sistema de archivos
  • API de teclado y joystick
  • API de matemáticas
  • API de ventana y mouse
  • API de física
  • API de sistema y temporizador

Motor grito

CryEngine es un motor de juego desarrollado por el desarrollador de juegos alemán Crytek. Ha evolucionado de la generación 1 a la generación 4 y es una solución de desarrollo avanzada. Es compatible con juegos de PC, Xbox 360, PlayStation3 y WiiU.

Proporciona múltiples funciones que incluyen,

  • Efectos visuales como iluminación natural y sombras suaves dinámicas, iluminación global dinámica en tiempo real, volumen de propagación de luz, sombreado de partículas, teselación, etc.

  • Sistema de animación de personajes y sistema de individualización de personajes.

  • Animación esquelética paramétrica y editor exclusivo de animación facial dedicado

  • Sistemas de inteligencia artificial como la malla de navegación multicapa y el sistema de puntos tácticos. También proporciona un sistema de edición de IA fácil de diseñar.

  • En Mezcla y creación de perfiles de juegos, Sistema de sonido basado en datos Sonidos dinámicos y Música interactiva, etc.

  • Funciones de física como Deformación por procedimientos y Física avanzada de cuerdas.

Una nota final

Cada uno de estos SDK / frameworks de juegos tiene sus propias ventajas y desventajas. Una elección adecuada entre ellos facilita su tarea y puede pasar un mejor momento con ella. Entonces, antes de usarlo, debes conocer los requisitos de tu juego y luego analizar cuál satisface todas tus necesidades y luego debes usarlos.

Las bibliotecas estándar de Lua proporcionan un amplio conjunto de funciones que se implementan directamente con la API de C y están integradas con el lenguaje de programación Lua. Estas bibliotecas brindan servicios dentro del lenguaje de programación Lua y también servicios externos como operaciones de archivos y bases de datos.

Estas bibliotecas estándar integradas en la API oficial de C se proporcionan como módulos C separados. Incluye lo siguiente:

  • Biblioteca básica, que incluye la subbiblioteca de rutinas
  • Biblioteca de módulos
  • Manipulación de cuerdas
  • Manipulación de mesa
  • Biblioteca de matemáticas
  • Entrada y salida de archivos
  • Instalaciones del sistema operativo
  • Instalaciones de depuración

Biblioteca básica

Hemos utilizado la biblioteca básica a lo largo del tutorial en varios temas. La siguiente tabla proporciona enlaces de páginas relacionadas y enumera las funciones que se tratan en varias partes de este tutorial de Lua.

No Señor. Biblioteca / Método y propósito
1

Error Handling

Incluye funciones de manejo de errores como afirmar, error como se explica en Lua - Manejo de errores .

2

Memory Management

Incluye las funciones de administración automática de memoria relacionadas con la recolección de basura como se explica en Lua - Recolección de basura .

3

dofile ([filename])

Abre el archivo y ejecuta el contenido del archivo como un fragmento. Si no se pasa ningún parámetro, esta función ejecuta el contenido de la entrada estándar. Los errores se propagarán a la persona que llama.

4

_G

Por tanto, es la variable global que contiene el entorno global (es decir, _G._G = _G). Lua en sí no usa esta variable.

5

getfenv ([f])

Devuelve el entorno actual en uso por la función. f puede ser una función Lua o un número que especifica la función en ese nivel de pila; el nivel 1 es la función que llama a getfenv. Si la función dada no es una función Lua, o si f es 0, getfenv devuelve el entorno global. El valor predeterminado de f es 1.

6

getmetatable (object)

Si el objeto no tiene una metatabla, devuelve nil. De lo contrario, si la metatabla del objeto tiene un campo "__metatable", devuelve el valor asociado. De lo contrario, devuelve la metatabla del objeto dado.

7

ipairs (t)

Esta función obtiene los índices y valores de las tablas.

8

load (func [, chunkname])

Carga un fragmento usando la función func para obtener sus partes. Cada llamada a func debe devolver una cadena que se concatene con los resultados anteriores.

9

loadfile ([filename]))

Similar a cargar, pero obtiene el fragmento del nombre del archivo o de la entrada estándar, si no se proporciona un nombre de archivo.

10

loadstring (string [, chunkname])

Similar a load, pero obtiene el fragmento de la cadena dada.

11

next (table [, index])

Permite que un programa recorra todos los campos de una tabla. Su primer argumento es una tabla y su segundo argumento es un índice en esta tabla. next devuelve el siguiente índice de la tabla y su valor asociado.

12

pairs (t)

Suspende la corrutina en ejecución. El parámetro pasado a este método actúa como valores de retorno adicionales a la función de reanudación.

13

print (...)

Suspende la corrutina en ejecución. El parámetro pasado a este método actúa como valores de retorno adicionales a la función de reanudación.

14

rawequal (v1, v2)

Comprueba si v1 es igual a v2, sin invocar ningún metamétodo. Devuelve un booleano.

15

rawget (table, index)

Obtiene el valor real de la tabla [índice], sin invocar ningún metamétodo. la mesa debe ser una mesa; El índice puede tener cualquier valor.

dieciséis

rawset (table, index, value)

Establece el valor real de la tabla [índice] en valor, sin invocar ningún metamétodo. La tabla debe ser una tabla, indexar cualquier valor diferente de nil y valorar cualquier valor Lua. Esta función devuelve la tabla.

17

select (index, ...)

Si el índice es un número, devuelve todos los argumentos después del índice del número de argumento. De lo contrario, index debe ser la cadena "#", y select devuelve el número total de argumentos adicionales que recibió.

18

setfenv (f, table)

Establece el entorno que utilizará la función dada. f puede ser una función Lua o un número que especifica la función en ese nivel de pila; el nivel 1 es la función que llama a setfenv. setfenv devuelve la función dada. Como caso especial, cuando f es 0, setfenv cambia el entorno del hilo en ejecución. En este caso, setfenv no devuelve ningún valor.

19

setmetatable (table, metatable)

Establece la metatabla para la tabla dada. (No puede cambiar la metatabla de otros tipos de Lua, solo de C.) Si metatabla es nil, elimina la metatabla de la tabla dada. Si la metatabla original tiene un campo "__metatable", genera un error. Esta función devuelve la tabla.

20

tonumber (e [, base])

Intenta convertir su argumento en un número. Si el argumento ya es un número o una cadena convertible en un número, tonumber devuelve este número; de lo contrario, devuelve nil.

21

tostring (e)

Recibe un argumento de cualquier tipo y lo convierte en una cadena en un formato razonable. Para tener un control completo de cómo se convierten los números, use string.format.

22

type (v)

Devuelve el tipo de su único argumento, codificado como una cadena. Los posibles resultados de esta función son "nil" (una cadena, no el valor nil), "número", "cadena", "booleano", "tabla", "función", "hilo" y "datos de usuario".

23

unpack (list [, i [, j]])

Devuelve los elementos de la tabla dada.

24

_VERSION

Una variable global (no una función) que contiene una cadena que contiene la versión actual del intérprete. El contenido actual de esta variable es "Lua 5.1".

25

Coroutines

Incluye las funciones de manipulación de corrutinas como se explica en Lua - Corutinas .

Biblioteca de módulos

La biblioteca de módulos proporciona las funciones básicas para cargar módulos en Lua. Exporta una función directamente en el entorno global: require. Todo lo demás se exporta en un paquete de tabla. Los detalles sobre la biblioteca de módulos se explican en el capítulo anterior Lua - Tutorial de módulos .

Manipulación de cuerdas

Lua proporciona un amplio conjunto de funciones de manipulación de cadenas. El tutorial anterior de Lua - Strings cubre esto en detalle.

Manipulación de mesa

Lua depende de las tablas en casi todas sus operaciones. El tutorial anterior de Lua - Tables cubre esto en detalle.

Entrada y salida de archivos

A menudo necesitamos una instalación de almacenamiento de datos en la programación y esto es proporcionado por las funciones de biblioteca estándar para E / S de archivos en Lua. Se trata en el tutorial anterior de Lua - File I / O.

Instalaciones de depuración

Lua proporciona una biblioteca de depuración que proporciona todas las funciones primitivas para que creemos nuestro propio depurador. Se trata en el tutorial anterior de depuración de Lua .

A menudo necesitamos operaciones matemáticas en cálculos científicos y de ingeniería y podemos aprovechar esto utilizando las matemáticas estándar de la biblioteca Lua. La lista de funciones disponibles en la biblioteca matemática se muestra en la siguiente tabla.

No Señor. Biblioteca / Método y propósito
1

math.abs (x)

Devuelve el valor absoluto de x.

2

math.acos (x)

Devuelve el arco coseno de x (en radianes).

3

math.asin (x)

Devuelve el arco seno de x (en radianes).

4

math.atan (x)

Devuelve el arco tangente de x (en radianes).

5

math.atan2 (y, x)

Devuelve el arco tangente de y / x (en radianes), pero usa los signos de ambos parámetros para encontrar el cuadrante del resultado. (También maneja correctamente el caso de que x sea cero).

6

math.ceil (x)

Devuelve el número entero más pequeño mayor o igual que x.

7

math.cos (x)

Devuelve el coseno de x (se supone que está en radianes).

8

math.cosh (x)

Devuelve el coseno hiperbólico de x.

9

math.deg (x)

Devuelve el ángulo x (expresado en radianes) en grados.

10

math.exp (x)

Devuelve el valor e potencia x.

11

math.floor (x)

Devuelve el número entero más grande menor o igual que x.

12

math.fmod (x, y)

Devuelve el resto de la división de x por y que redondea el cociente hacia cero.

13

math.frexp (x)

Devuelve my e tal que x = m2e, e es un número entero y el valor absoluto de m está en el rango [0.5, 1) (o cero cuando x es cero).

14

math.huge

El valor HUGE_VAL, un valor mayor o igual a cualquier otro valor numérico.

15

math.ldexp (m, e)

Devuelve m2e (e debe ser un número entero).

dieciséis

math.log (x)

Devuelve el logaritmo natural de x.

17

math.log10 (x)

Devuelve el logaritmo en base 10 de x.

18

math.max (x, ...)

Devuelve el valor máximo entre sus argumentos.

19

math.min (x, ...)

Devuelve el valor mínimo entre sus argumentos.

20

math.modf (x)

Devuelve dos números, la parte integral de x y la parte fraccionaria de x.

21

math.pi

El valor de pi.

22

math.pow (x, y)

Devuelve xy. (También puede usar la expresión x ^ y para calcular este valor).

23

math.rad (x)

Devuelve el ángulo x (dado en grados) en radianes.

24

math.random ([m [, n]])

Esta función es una interfaz para la función generadora pseudoaleatoria simple rand proporcionada por ANSI C. Cuando se llama sin argumentos, devuelve un número real pseudoaleatorio uniforme en el rango [0,1). Cuando se llama con un número entero m, math.random devuelve un entero pseudoaleatorio uniforme en el rango [1, m]. Cuando se llama con dos números enteros myn, math.random devuelve un entero pseudoaleatorio uniforme en el rango [m, n].

25

math.randomseed (x)

Establece x como la "semilla" para el generador pseudoaleatorio: las semillas iguales producen secuencias iguales de números.

26

math.sin (x)

Devuelve el seno de x (se supone que está en radianes).

27

math.sinh (x)

Devuelve el seno hiperbólico de x.

28

math.sqrt (x)

Devuelve la raíz cuadrada de x. (También puede usar la expresión x ^ 0.5 para calcular este valor).

29

math.tan (x)

Devuelve la tangente de x (se supone que está en radianes).

30

math.tanh (x)

Devuelve la tangente hiperbólica de x.

Funciones trigonométricas

A continuación se muestra un ejemplo sencillo que utiliza la función trigonométrica.

radianVal = math.rad(math.pi / 2)

io.write(radianVal,"\n")

-- Sin value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.sin(radianVal)),"\n")

-- Cos value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.cos(radianVal)),"\n")

-- Tan value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.tan(radianVal)),"\n")

-- Cosh value of 90(math.pi / 2) degrees
io.write(string.format("%.1f ", math.cosh(radianVal)),"\n")

-- Pi Value in degrees
io.write(math.deg(math.pi),"\n")

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

0.027415567780804
0.0 
1.0 
0.0 
1.0 
180

Otras funciones matemáticas comunes

A continuación se muestra un ejemplo sencillo que utiliza funciones matemáticas comunes.

-- Floor
io.write("Floor of 10.5055 is ", math.floor(10.5055),"\n")

-- Ceil
io.write("Ceil of 10.5055 is ", math.ceil(10.5055),"\n")

-- Square root
io.write("Square root of 16 is ",math.sqrt(16),"\n")

-- Power
io.write("10 power 2 is ",math.pow(10,2),"\n")
io.write("100 power 0.5 is ",math.pow(100,0.5),"\n")

-- Absolute
io.write("Absolute value of -10 is ",math.abs(-10),"\n")

--Random
math.randomseed(os.time())
io.write("Random number between 1 and 100 is ",math.random(),"\n")

--Random between 1 to 100
io.write("Random number between 1 and 100 is ",math.random(1,100),"\n")

--Max
io.write("Maximum in the input array is ",math.max(1,100,101,99,999),"\n")

--Min
io.write("Minimum in the input array is ",math.min(1,100,101,99,999),"\n")

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado.

Floor of 10.5055 is 10
Ceil of 10.5055 is 11
Square root of 16 is 4
10 power 2 is 100
100 power 0.5 is 10
Absolute value of -10 is 10
Random number between 1 and 100 is 0.22876674703207
Random number between 1 and 100 is 7
Maximum in the input array is 999
Minimum in the input array is 1

Los ejemplos anteriores son solo algunos de los ejemplos comunes, podemos usar la biblioteca matemática según nuestras necesidades, así que intente usar todas las funciones para estar más familiarizado.

En cualquier aplicación, a menudo se requiere para acceder a las funciones de nivel del sistema operativo y está disponible con la biblioteca del sistema operativo. La lista de funciones disponibles se enumeran en la siguiente tabla.

No Señor. Biblioteca / Método y propósito
1

os.clock ()

Devuelve una aproximación de la cantidad en segundos de tiempo de CPU utilizado por el programa.

2

os.date ([format [, time]])

Devuelve una cadena o una tabla que contiene la fecha y la hora, formateada según el formato de cadena dado.

3

os.difftime (t2, t1)

Devuelve el número de segundos desde el tiempo t1 hasta el tiempo t2. En POSIX, Windows y algunos otros sistemas, este valor es exactamente t2-t1.

4

os.execute ([command])

Esta función es equivalente al sistema de funciones ANSI C. Pasa un comando para que lo ejecute un shell del sistema operativo. Su primer resultado es verdadero si el comando terminó con éxito, o nulo en caso contrario.

5

os.exit ([code [, close])

Llama a la función de salida ANSI C para terminar el programa anfitrión. Si el código es verdadero, el estado devuelto es EXIT_SUCCESS; si el código es falso, el estado devuelto es EXIT_FAILURE; si el código es un número, el estado devuelto es este número.

6

os.getenv (varname)

Devuelve el valor de la variable de entorno del proceso varname, o nil si la variable no está definida.

7

os.remove (filename)

Elimina el archivo (o directorio vacío, en sistemas POSIX) con el nombre dado. Si esta función falla, devuelve nil, más una cadena que describe el error y el código de error.

8

os.rename (oldname, newname)

Cambia el nombre del archivo o directorio llamado oldname a newname. Si esta función falla, devuelve nil, más una cadena que describe el error y el código de error.

9

os.setlocale (locale [, category])

Establece la configuración regional actual del programa. locale es una cadena dependiente del sistema que especifica una locale; categoría es una cadena opcional que describe qué categoría cambiar: "todo", "cotejar", "ctype", "monetario", "numérico" o "tiempo"; la categoría predeterminada es "todos". La función devuelve el nombre de la nueva configuración regional o nil si la solicitud no se puede cumplir.

10

os.time ([table])

Devuelve la hora actual cuando se llama sin argumentos, o una hora que representa la fecha y hora especificadas por la tabla dada. Esta tabla debe tener campos año, mes y día, y puede tener campos hora (el valor predeterminado es 12), min (el valor predeterminado es 0), sec (el valor predeterminado es 0) e isdst (el valor predeterminado es cero). Para obtener una descripción de estos campos, consulte la función os.date.

11

os.tmpname ()

Devuelve una cadena con un nombre de archivo que se puede utilizar para un archivo temporal. El archivo debe abrirse explícitamente antes de su uso y eliminarse explícitamente cuando ya no sea necesario.

Funciones comunes del sistema operativo

A continuación se muestra un ejemplo sencillo que utiliza funciones matemáticas comunes.

-- Date with format
io.write("The date is ", os.date("%m/%d/%Y"),"\n")

-- Date and time
io.write("The date and time is ", os.date(),"\n")

-- Time
io.write("The OS time is ", os.time(),"\n")

-- Wait for some time
for i=1,1000000 do
end

-- Time since Lua started
io.write("Lua started before ", os.clock(),"\n")

Cuando ejecutamos el programa anterior, obtendremos un resultado similar al siguiente.

The date is 01/25/2014
The date and time is 01/25/14 07:38:40
The OS time is 1390615720
Lua started before 0.013

Los ejemplos anteriores son solo algunos de los ejemplos comunes, podemos usar la biblioteca del sistema operativo según nuestras necesidades, así que intente usar todas las funciones para estar más familiarizado. Hay funciones como eliminar que ayuda a eliminar archivos, ejecutar que nos ayuda a ejecutar los comandos del sistema operativo como se explicó anteriormente.