Tutorial de Lua
Lua es un lenguaje de scripting desarrollado en Brasil a principios de los años 90. El código fuente de un programa redactado en Lua es traducido a bytecode por un intérprete de Lua, que también lo ejecuta. El intérprete en sí está escrito en el lenguaje C, lo cual otorga a los programas escritos en Lua un mayor rendimiento al ejecutarse. Además, la API de C permite embeber (es decir, insertar) código Lua en programas en C / C++. Lua es un lenguaje multiparadigma pensado para redactar código imperativo, funcional y orientado a objetos.
La característica que hace único a Lua es que puede embeberse (incrustarse) de forma muy sencilla en otros sistemas y lenguajes. Por este motivo, Lua se ha convertido en un importante lenguaje pegamento (glue language) y se usa en muchos motores de videojuego. También puede usarse para dirigir servidores web como Apache y nginx. A través de la interfaz de entrada común (o CGI, por sus siglas en inglés), Lua también es usado a menudo como lenguaje de programación para Internet de forma autónoma. Por si eso fuera poco, también es usado para programar apps móviles.
Tutorial para aprender Lua: primeros pasos
La manera más rápida y sencilla de aprender a programar en Lua es ejecutar código desde la interactiva plataforma demo de Lua. Allí podrás poner a prueba todos los ejemplos de código que mostramos en este artículo. Para ello, copia alguno de los ejemplos en el campo de texto y haz clic en “run” para ejecutarlo.
De este modo, puedes ahorrarte la instalación. Si, en cambio, quieres usar Lua en tu propio sistema, sigue leyendo y te explicamos cómo. De lo contrario, puedes saltar directamente al apartado “Aprender las bases de Lua”.
Preparar tu sistema para el tutorial de Lua
El intérprete de Lua está compuesto por un único archivo binario, que se abrirá al ejecutar la orden “lua” en la línea de comandos. El archivo se guarda entonces en el sistema y se le adjudica, si es necesario, una ruta. Los usuarios de Lua también tienen bibliotecas a su disposición que hacen posible la incrustación de código Lua en programas en C / C++.
Si quieres instalar Lua en Mac o Linux, el gestor de paquetes Homebrew es una muy buena opción. Una vez hayas instalado Homebrew, utiliza simplemente el comando que aparece a continuación para instalar Lua:
Para instalar Lua en un sistema Windows, en cambio, puedes usar el gestor de paquetes LuaDist.
Aprender Lua: cómo usar el intérprete de Lua de forma interactiva
Al igual que ocurre en muchos lenguajes de scripting, el intérprete de Lua también puede ejecutarse en modo interactivo. En este modo, el intérprete toma el código Lua de la línea de comandos y lo ejecuta línea a línea. Los valores generados como resultado se muestran directamente en la línea de comandos y el usuario puede entonces comprobar y modificar los valores de las variables. Por eso, este método resulta especialmente útil para crear prototipos rápidos. Para iniciar el intérprete de Lua en modo interactivo, introduce la siguiente orden en la línea de comandos:
Para desactivar de nuevo el modo interactivo, introduce la orden “os.exit()” o usa la combinación de teclas [Ctrl]+[C].
Tutorial de Lua: ejecutar código Lua con el intérprete
En lugar de ir pegando fragmentos de código en la línea de comandos, puedes ordenarle al intérprete de Lua que ejecute el archivo con el código fuente al completo. Para ello, primero hay que crear un archivo Lua y luego indicar su nombre al intérprete para que lo ejecute. El intérprete procesará el código fuente del archivo línea a línea y lo ejecutará.
Los archivos de código fuente Lua tienen la extensión “.lua”.
Tutorial de Lua: ejecutar directamente código Lua usando un shebang
En sistemas operativos Linux / UNIX / macOS también es posible hacer que un archivo de código fuente en Lua sea directamente ejecutable. Para ello, introduce un hashbang (también llamado shebang) como primera línea en el archivo Lua:
Como puedes ver, el hashbang contiene la ubicación del archivo binario de Lua, que en nuestro caso es “#!/usr/local/bin/lua”. En algunas ocasiones, la ubicación en tu sistema podría diferir de la que se indica, pero en tal caso podrás indicar la ubicación correcta del archivo binario. Para hacerlo, introduce la orden “which”en la línea de comandos:
Una vez hayas añadido el hashbang al código Lua, marca el archivo para indicar que puede ser ejecutado por el usuario. Para ello, introduce la siguiente orden en la línea de comandos:
A continuación, ejecuta el código Lua en el directorio actual:
El truco del hashbang funciona en Linux y en sistemas tipo UNIX, como macOS, con la mayoría de lenguajes de scripting. También se puede aplicar el mismo proceso a códigos Ruby o Python para hacerlos ejecutables.
Aprender las bases de Lua
Lua es un lenguaje multiparadigma y con un estilo de base imperativo y funcional. Se trata de un lenguaje totalmente dinámico, por lo que no distingue entre “compile time” y “run time”. Además, apuesta sin excepción por una gestión dinámica de la memoria, es decir, permite que el tamaño de un objeto almacenado cambie durante el tiempo de ejecución. De eliminar datos innecesarios para liberar espacio se encarga un garbage collector (GC), así los programadores pueden dedicarse a otras tareas.
Cómo utilizar los comentarios en el código Lua
Los comentarios son un elemento esencial de cualquier lenguaje de programación. Estas son algunas de sus funciones más importantes:
- Esbozar partes del código
- Documentar características del código
- Activar o desactivar líneas de código
En Lua, un comentario de una sola línea comienza con dos guiones (“--”) y acaba donde acaba la línea:
Tutorial de Lua: valores y tipos
Lua, al igual que la mayoría de lenguajes de scripting, es un lenguaje tipificado dinámicamente, es decir, un lenguaje en el que los tipos no están asociados a variables, sino a valores. Cada valor tiene un solo tipo asociado, ya sea número, secuencia de caracteres, valor lógico, etc. En total, Lua comprende una cantidad no muy abrumadora de tipos, que hemos resumido en la siguiente tabla:
Tipo | Explicación |
number | Número decimal |
string | Secuencia de caracteres |
boolean | Valor lógico: “true” o “false” |
nil | Falta este valor; el tipo solo tiene el valor “nil” |
function | Función |
table | Tipo de dato compuesto: “List” / “Array”, “Hash” / “Dictionary” |
thread | Corrutina |
userdata | Tipo de dato C definido por el usuario |
Lua puede aplicar sintaxis literal a los valores de todos los tipos, a excepción de “thread” y “userdata”. Para indicar el tipo de un valor se utiliza la función “type()”, que devuelve el nombre del tipo en forma de string (es decir, como una secuencia de caracteres). A continuación presentamos un par de ejemplos:
Ten en cuenta que, como podrás ver en los siguientes ejemplos, Lua no asigna el índice 0 al primer elemento de una lista (como sí hacen la mayoría de lenguajes), ¡sino el índice 1!
Programar en Lua: ¿qué son las expresiones, las variables y los operadores?
Las expresiones (expressions) son evaluadas por el intérprete y devuelven un valor como resultado. Además, combinan literales, operadores, variables y llamadas de función; y pueden agruparse, si se quiere, entre paréntesis “()”. Puesto que se trata de un lenguaje dinámico, Lua muestra automáticamente el tipo del valor de retorno. Estos son algunos ejemplos de expresiones:
Una variable es el nombre de un valor en la memoria. Al igual que en la mayoría de lenguajes de programación, en Lua los nombres empiezan con una letra o un guion bajo (_) al que siguen otras letras, guiones bajos o cifras. La distinción entre letras en mayúscula o en minúscula es muy importante en estos nombres. Sin embargo, ciertas palabras se reservan para usos concretos y no pueden usarse, por sí solas, como nombres:
and, end, in, repeat, break, false, local, return, do, for, nil, then, else, function, not, true, elseif, if, or, until, while
Estas palabras sí pueden usarse, en cambio, como parte de un nombre más largo:
La asignación de un valor a una variable se realiza mediante el operador de asignación (=), que no debe confundirse con el operador lógico de igualdad (==). Como es habitual, al asignar valores se distingue entre “L-value” y “R-value”: la variable debe estar en el lado izquierdo del operador de asignación, por lo que pasa a ser el “L-value”. A dicho valor se le asigna el valor evaluado del “R-value”, que está a la derecha del operador.
Los operadores (operators) generan un nuevo valor a partir de uno o más operandos. Existen operadores unarios (que solo necesitan un argumento) y binarios (que necesitan dos). Su función consiste en conectar operandos de un tipo concreto y devolver un valor de un tipo concreto. A continuación, presentamos los diferentes operadores que encontramos en Lua.
Los operadores aritméticos operan con cifras y devuelven otra cifra:
Operador aritmético | Aridad | Operación |
+ | binario | Suma |
- | binario | Resta |
* | binario | Multiplicación |
/ | binario | División |
% | binario | Operación módulo (residuo) |
^ | binario | Potencia |
- | unario | Negación |
Los operadores relacionales, todos ellos binarios, comprueban cómo reaccionan dos operandos entre sí y devuelven un valor lógico:
Operador relacional | Prueba |
== | Igualdad |
~= | Desigualdad |
> | Mayor que |
< | Menor que |
>= | Mayor que o igual |
<= | Menor que o igual |
Los operadores lógicos asocian valores lógicos y devuelven otro valor lógico:
Operador lógico | Aridad | Operación |
and | binario | Asociación “y” |
or | binario | Asociación “o” |
not | unario | Negación |
Además de los operadores mencionados, en Lua existen dos operadores especiales que sirven para concatenar strings (es decir, para encadenar secuencias de caracteres) y para indicar el tamaño de un valor compuesto, como puede ser “table” o “string”:
Operador | Aridad | Operación |
.. | binario | Concatenación de strings |
# | unario | Indicar el número de elementos de una tabla / la longitud de una string |
En Lua no se utilizan operadores de asignación compuestos, como lo son, por ejemplo, “+=” y “-=” en muchos otros lenguajes de scripting. Para incrementar y decrementar variables, por lo tanto, se redacta explícitamente la operación:
Tutorial de Lua: ámbitos de validez y bloques
El concepto de ámbito de validez es clave en todos los lenguajes de programación, ya que las variables solo existen dentro de un ámbito de validez determinado. Al igual que en JavaScript, las variables en Lua son globales en la configuración por defecto. Sin embargo, el uso continuo de variables globales es lo que se conoce como antipatrón o anti-pattern y debería evitarse. Para conseguirlo, en Lua existe la palabra clave “local”, que limita el ámbito de validez de una variable al bloque que la rodea. Se trata de un efecto similar al que provoca “let” en JavaScript.
En Lua, los cuerpos de las funciones y los bucles abren un nuevo ámbito de validez. Lua utiliza, además, los llamados bloques explícitos. Cada bloque define un nuevo ámbito de validez para el código ubicado entre las palabras clave “do” y “end”. Estas palabras corresponden, respectivamente, a las llaves de apertura y de cierre “{” y “}” en Java / C / C++. El siguiente ejemplo de código muestra cómo están relacionados entre ellos los bloques, los ámbitos de validez y las variables:
Programar en Lua con estructuras de control
Lua también reconoce las estructuras de control habituales que se encuentran en otros lenguajes de programación, entre las que se encuentran las bifurcaciones y los bucles. A continuación, presentamos un ejemplo con órdenes “if”, “then”, “else” y “elseif” en Lua:
Además del típico bucle con “while”, Lua también admite su contraparte, el bucle con “repeat” y “until”, que también se usa en Ruby y que requiere que se invierta la condición aplicada. Eso significa que un “while” con la condición “número </= límite” se corresponde con un “repeat”-“until” con la condición “número > límite”. ¡Ten cuidado con la orden “repeat”! Independientemente de la condición, el cuerpo del bucle se ejecutará al menos una vez. He aquí un ejemplo:
Tal y como ocurre con la mayoría de lenguajes imperativos, Lua no solo reconoce el bucle con “while”, sino también una orden con “for”, que puede adoptar dos formas: una variante similar a la del lenguaje C, con variable de bucle, y una variante con iterador. En el siguiente ejemplo mostramos el uso de la orden “for” con variable de bucle:
Sorprendentemente, la variable de bucle definida en el bucle de “for” es local, no global, sin necesidad de haber sido declarada explícitamente como “local”. Esto resulta muy conveniente y es uno de los aspectos en los que Lua aventaja a JavaScript. En este último lenguaje, toda variable de bucle que no esté declarada con “let” o “var” es global, lo cual puede provocar graves fallos.
Ahora, nos ocuparemos del bucle de “for” con iterador en Lua. En principio, el concepto es similar al de Python: en lugar de incrementar una variable de bucle y usarla como índice (“index”) en una lista, se itera directamente a través de los elementos de la lista. Para generar el iterador suele usarse la función “ipairs()”, como muestra el siguiente ejemplo:
Más funciones en Lua
En Lua, al igual que en C / C++, Java y JavaScript, las funciones se definen con la palabra clave “function”. Como es habitual, tras el nombre de la función aparecen los parámetros correspondientes entre paréntesis. Lo que caracteriza a Lua en este sentido es que en la llamada de función pueden omitirse los paréntesis con tan solo un literal como argumento. Una función de Lua no ha de devolver necesariamente un valor. En caso de que no haya valor, se habla por definición de un “procedimiento”:
Para obtener de vuelta un valor a partir de una función, se usa, como es habitual, la palabra clave “return”. Esta palabra finaliza la ejecución de la función y hace que se vuelva a mostrar el valor indicado. En el siguiente ejemplo de código hemos obtenido el cuadrado de un número:
Al igual que en Python y JavaScript, en Lua una función puede aceptar una cantidad variable de argumentos. Los argumentos se guardan en el constructo especial “(...)”. Para acceder a ellos, suele ser útil resumirlos con la expresión “{...}” en una lista. Otra manera de hacerlo es usando la función “select()”, que extrae un argumento del índice indicado. Para indicar el número de argumentos se utiliza la expresión “#{...}”.
Además de aceptar un número variable de argumentos, Lua también permite que se devuelvan varios valores con una orden “return”. Esta opción es similar a la que ofrece Python, pero sin el tipo explícito “Tupel”. Otro punto en común entre Lua y Python es que en ambos es habitual asignar los valores de retorno a más de una variable al llamar la función. He aquí un ejemplo:
Si alguno de los valores de retorno no es necesario, por lo general se usa el guion bajo (_) como marcador de posición, como podemos ver en el siguiente ejemplo:
En Lua, las funciones son first-class citizens, es decir, pueden asociarse a variables y, así, pueden transferirse también como argumento a otras funciones. Además, una función en Lua puede funcionar como valor de retorno de otra función. Gracias a todas estas posibilidades, Lua hace posible una programación funcional, que ilustramos a continuación con el ejemplo de la famosa función “map()”:
En la programación funcional es habitual el uso de la recursividad, es decir, que una función se llame a sí misma una y otra vez con argumentos modificados. En el caso de Lua, debemos tener especial cuidado con las funciones llamadas de forma recursiva, que debemos declarar explícitamente como “local”.