# Tipos de datos Lua es un lenguaje de tipos dinámicos. Al igual que en otros lenguajes dinámicos, el tipo de una variable es inferido en función del valor asignado. En esta afirmación hay que tener en cuenta dos conceptos: - Declaración - Asignación Cuando hablamos de lenguajes de tipos estáticos, como por ejemplo C, C++, C#, Java entre otros, realizamos las dos operaciones. Primero declaramos la variable, que tiene que ser obligatoriamente de un tipo y luego le asignamos un valor, que debe ser concordante con el tipo declarado. En Lua y en otros lenguajes dinámicos, se hacen las dos operaciones durante la asignación. Esto quiere decir que cuando hacemos una asignación `a = "Valor"`, estamos declarando una variable `a`, a la cual le asignamos el valor `"Valor"`. A partir del valor asignado, el intérprete de Lua es capaz de 'adivinar' el tipo. En el caso de nuestro ejemplo, `"Valor"` es un literal de cadena y entonces la variable `a` será del tipo `string`. Dicho esto, si intentamos declarar una variable en Lua sin asignarle un valor, el intérprete nos dará un error. --- ### Tipos básicos de Lua En Lua se definen ocho tipos básicos:
**nil**Representa un valor nulo o inválido
**boolean**Representa un valor booleano: verdadero, falso
**number**Representa un número real en coma flotante de doble precisión
**string**Representa una cadena de caracteres
**function**Referencia a una función declarada
**userdata**Representa cualquier otro tipo de datos almacenados en la variable
**thread**Referencia un hilo para entornos multi-hilo
**table**Referencia a un array asociativo multidimensional
Podemos conocer el tipo de una variable en todo momento usando la función `type()`: ```lua print(type(11.6)) --> number print(type("Hola Mundo")) --> string print(type(print)) --> function print(type(false)) --> boolean print(type(nil)) --> string print(type({a = 1})) --> table ``` --- #### nil El tipo `nil` indica que no hay valor definido. Si el valor es retornado para una variable, quiere decir que la variable no está definida. Si este valor es retornado por una función significa que no hay valor a devolver. Por ejemplo: ```lua > print(a) nil ``` En el ejemplo anterior se intenta imprimir el valor de una variable `a`, pero el valor devuelto es `nil`. En este caso significa que la variable no ha sido declarada y por lo tanto no tiene valor. Recuerda que toda variable que se le asigne el valor `nil` desaparece, porque para que exista, debe tener un valor asignado diferente de `nil`. Cuando se asigna `nil` a un elemento de una tabla, al igual que en las variables, este elemento es anulado y por consiguiente, eliminado. Si se asigna `nil` a una variable que tiene una referencia a una tabla, la tabla entera será anulada y eliminada. Escribe el siguiente código en un archivo y ejecútalo con Lua para ver un ejemplo que te permita comprender mejor este concepto: ```lua tabla1 = { elm1 = "val 1", elm2 = "val 2", elm3 = "val 3" } for k, v in pairs(tabla1) do print(k .. " _ " .. v) end tabla1.elm2 = nil for k, v in pairs(tabla1) do print(k .. " _ " .. v) end ``` El resultado es el siguiente: ```bash elm3 _ val 3 elm2 _ val 2 elm1 _ val 1 elm3 _ val 3 elm1 _ val 1 ``` Podemos ver que las tres primeras lineas corresponden a los tres elementos de la tabla. Pero en las dos últimas, falta el elemento `elm2` que hemos eliminado asignándole `nil`. --- #### boolean Los tipos boolean representan dos posibles valores: true o false. Puedes probar el siguiente código para entender mejor el concepto: ```lua a = true b = false function PrintValue(value) if value then print("Verdadero") else print("Falso") end end PrintValue(a) --> a = true PrintValue(b) --> b = false ``` El ejemplo produce la siguiente salida: ```bash Verdadero Falso ``` --- #### number En Lua existe un solo tipo numérico con el que se pueden representar varios formatos numéricos, por ejemplo: - 5 - 5.1 - 0.6 - 3e+2 - 0.4e-1 - 3.423946103e+06 --- #### string Este tipo representa una cadena de caracteres. Esta cadena se puede delimitar usando comillas dobles (") o comillas simples (') indistintamente. Así por ejemplo son expresiones de cadenas válidas: ```lua cadena1 = "Cadena con comillas dobles" cadena2 = 'Cadena con comillas simples' ``` Cuando queremos asignar una cadena que contiene múltiples lineas, podemos usar dobles corchetes "\[\[\]\]" para englobar toda la cadena: ```lua text = [[ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ornare viverra augue, nec auctor sem pellentesque ac. Nulla at varius quam. Ut velit augue, ornare a sapien et, ultricies egestas mauris. Nam augue nibh, vulputate ut sagittis eu, vulputate imperdiet dolor. ]] ``` Si realizamos una operación matemática entre un tipo numérico y un tipo string, el intérprete de Lua intentará convertir la cadena de texto en un valor numérico y realizar la operación después. Si la cadena no puede ser convertida a un número el intérprete dará un error: ```bash > print(8 + "2") 10 > print("8" + "2") 10 > print("8 + 2") 8 + 2 > print("3e2" * "3") 900 > print("numero" + 5) stdin:1: attempt to perform arithmetic on a string value stack traceback: stdin:1: in main chunk [C]: in ? ``` Dos o más cadenas de texto se pueden concatenar usando dos puntos consecutivos (..) entre las cadenas o variables: ```bash > a = "Conca" > b = "tenación" > print(a .. b) Concatenación > print("Conca" .. "tenación") Concatenación ``` Se puede obtener la longitud de una cadena usando el operador almohadilla (#): ```bash > cadena = "Longitud" > longitud = #cadena > print(longitud) 8 > print(#cadena) 8 > print(#"Longitud") 8 ``` --- #### table El tipo table corresponde a un array asociativo, esto significa, que podemos usar números y cadenas para indizar los elementos. Del mismo modo, el array puede ser multinivel. Podemos inicializar una tabla vacía o añadiendo elementos: ```lua tabla1 = {} tabla2 = { "naranja", "manzana", "piña", "plátano" } ``` En una tabla, los índices no tienen que ser necesariamente del mismo tipo, pudiendo existir índices de tipo cadena y de tipo numérico: ```lua tbl = {} tbl["indice"] = "valor" i = 5 tbl[i] = 10 tbl[i] = tbl[i] + 5 for k, v in pairs(tbl) do print(k .. " : " .. v) end ``` Si ejecutamos el código anterior obtenemos el siguiente resultado: ```bash $ lua TestTableIndices.lua indice : valor 5 : 15 ``` Las tablas en Lua son de índice 1, esto significa que por defecto, el primer elemento de una tabla cuando no se especifiquen índices explícitamente será 1. Esto marca una diferencia con multitud de lenguajes cuyos arrays son de índice 0. Veamos un ejemplo: ```lua tabla = { "naranja", "manzana", "pera", "uva" } for k, v in pairs(tabla) do print("Índice: " .. k .. ", Valor: " .. v) end ``` Cuyo resultado es: ```bash $ lua TestTableIndices2.lua Indice: 1, Valor: naranja Indice: 2, Valor: manzana Indice: 3, Valor: pera Indice: 4, Valor: uva ``` Las tablas en Lua son dinámicas por lo que no tienen un tamaño definido. Una tabla irá ajustando su tamaño en función del número de elementos que contenga automáticamente. Eso quiere decir, que es el intérprete de Lua quien se ocupa de gestionar la memoria necesaria para almacenar los elementos de la tabla. --- #### function El tipo function almacena una referencia a una función. Esto significa que podemos asignar una función a una variable para usarla después: ```lua function factorial(n) if n == 0 then return 1 else return n * factorial(n - 1) end end print(factorial(4)) factorialVar = factorial print(factorialVar(4)) ``` Al ejecutar el código anterior obtenemos el siguiente resultado: ```bash $ lua TestTipoFunction.lua 24 24 ``` El tipo function también acepta las funciones anónimas pasadas como parámetros: ```lua function Anonima(tbl, fun) for k, v in pairs(tbl) do print(fun(k, v)) end end tabla = { clave1 = "valor1", clave2 = "valor2" } Anonima(tabla, function(clave, valor) return clave .. " = " .. valor\nend) ``` El resultado del código anterior es el siguiente: ```bash $ lua TestFunctionAnonima.lua clave2 = valor2 clave1 = valor1 ``` --- #### thread Las variables de tipo thread contienen referencias a hilos gestionados por el sistema operativo. Estos hilos permiten la realización de tareas en paralelo pero, pueden ser bastante difíciles de manejar. Como alternativa a los hilos, Lua maneja las llamadas corutinas, que permiten cierto paralelismo usando un solo hilo. Las corutinas son gestionadas directamente por el intérprete de Lua. --- #### userdata Las variables de tipo userdata contienen referencias a datos arbitrarios de C de cualquier tipo. En este tipo de datos se suelen almacenar referencias a estructuras y punteros.