Cuando llegas a Lua después de Python o JS y descubres que no hay matrices, ni objetos, ni diccionarios... Solo hay tablas.
Tu cara: 😐
Mi cara una semana después, cuando me di cuenta del poder de las tablas: 🤯
Veamos por qué las tablas en Lua no son una «pobreza del lenguaje», sino un diseño ingenioso que los principiantes subestiman constantemente.

Espera, ¿de verdad solo hay tablas aquí?
Sí. Una estructura de datos para todas las ocasiones. ¿Quieres una matriz? Una tabla. ¿Un diccionario? Tabla. ¿Objeto con métodos? Adivinaste, una tabla. ¿Cola, pila, grafo, árbol? Todas las tablas.
Desarrollador de Lua explicando la arquitectura del proyecto:
— Y aquí tenemos una tabla de tablas que almacena tablas con tablas.
— Entiendo, gracias.
Suena a locura, pero en la práctica es increíblemente elegante.
Tabla como matriz: indexación desde uno (sí, desde UNO)
Aquí está el primer shock para cualquiera que venga del mundo de los idiomas normales:
local fruits = {"apple", "banana", "cherry"}
print(fruits[1]) -- "apple"
print(fruits[0]) -- nil 😭Indexación con 1. No desde cero. Desde la UNIDAD.
Cada antiguo programador de C siente dolor físico en este momento. Pero Lua tiene sus razones: el lenguaje fue diseñado para personas que no tienen conocimientos de programación (ingenieros, diseñadores), y para ellos «el primer elemento = 1» es lógico.
Te acostumbras en un par de días. Sufres las dos primeras horas.
Clásicos útiles: iteración de matrices
local heroes = {"Lua", "Python", "JavaScript"}
for i, name in ipairs(heroes) do
print(i .. ". " .. name)
end
-- 1. Lua
-- 2. Python
-- 3. JavaScriptipairs — recorre los índices numéricos en orden. Recuérdalo, estará en todas partes.
Tabla como diccionario: clave-valor con esteroides
Aquí es donde comienza la magia. La tabla puede ser a la vez una matriz y un diccionario:
local player = {
name = "ProGamer228",
level = 42,
hp = 100,
"hidden achievement" -- это индекс [1]
}
print(player.name) -- "ProGamer228"
print(player["level"]) -- 42
print(player[1]) -- "hidden achievement"Dos formas de acceso: a través del punto (player.name) y a través de paréntesis (player["name"]). Los corchetes son necesarios cuando la clave es una variable o contiene caracteres especiales.
local key = "hp"
print(player[key]) -- 100
-- Ключом может быть вообще что угодно
local weird = {}
weird[true] = "yes"
weird[3.14] = "pi"
weird[print] = "function as a key, why not"La clave puede ser cualquier tipo excepto nil. Esto abre posibilidades increíbles, pero no se debe abusar de ello: la legibilidad del código también es importante.
Longitud de la tabla: aquí todo es complicado
El operador # devuelve la longitud de la parte "masiva" de la tabla:
local t = {10, 20, 30, 40}
print(#t) -- 4 ✅
local mixed = {10, 20, nil, 40}
print(# mixed) -- puede ser 2, o puede ser 4 🤡Regla importante: si en la parte masiva hay nil — el comportamiento # no está definido. Lua puede devolver cualquier número. Esto no es un error, es por diseño. Simplemente no dejes agujeros en las matrices.
¿Quieres una longitud fiable para los diccionarios? Cuenta manualmente:
local function tableLength(t)
local count = 0
for _ in pairs(t) do
count = count + 1
end
return count
endTabla como objeto: programación orientada a objetos en Lua
En Lua no hay clases. ¿Pero a quién le ha parado eso?
local Dog = {}
Dog.__index = Dog
function Dog.new(name, breed)
local self = setmetatable({}, Dog)
self.name = name
self.breed = breed
return self
end
function Dog:bark()
print(self.name .. " says: WOOF!")
end
function Dog:info()
print(self.name .. " - breed: " .. self.breed)
end
local rex = Dog.new("Rex", "Shepherd")
rex:bark() -- Рекс говорит: ГАВ!
rex:info() -- Рекс — порода: ОвчаркаPresta atención a los dos puntos (:) en lugar de un punto al llamar a un método: es un azúcar sintáctico que transmite automáticamente el objeto como self. Sin esto, tendríamos que escribir rex.bark(rex), y se vería triste.
¿Herencia? También a través de tablas
local Puppy = setmetatable({}, {__index = Dog})
Puppy.__index = Puppy
function Puppy.new(name, breed, toy)
local self = Dog.new(name, breed)
setmetatable(self, Puppy)
self.toy = toy
return self
end
function Puppy:play()
print(self.name .. " plays with " .. self.toy .. "!")
end
local baby = Puppy.new("Bobik", "Corgi", "ball")
baby:bark() -- Бобик говорит: ГАВ! (унаследовано от Dog)
baby:play() -- Бобик играет с мячиком!Metatablas y __index - es el corazón del sistema de objetos Lua. Cuando no se encuentra un campo en la tabla actual, Lua busca en la metatabla __index. La cadena puede ser tan larga como quieras, aquí tienes la herencia.

Metamétodos: sobrecargamos todo
Las metatablas permiten redefinir el comportamiento de la tabla para las operaciones estándar:
local Vector = {}
Vector.__index = Vector
function Vector.new(x, y)
return setmetatable({x = x, y = y}, Vector)
end
-- Перегружаем оператор сложения
function Vector.__add(a, b)
return Vector.new(a.x + b.x, a.y + b.y)
end
-- Перегружаем вывод через tostring
function Vector.__tostring(v)
return "(" .. v.x .. ", " .. v.y .. ")"
end
local v1 = Vector.new(1, 2)
local v2 = Vector.new(3, 4)
local v3 = v1 + v2
print(tostring(v3)) -- (4, 6)Los principales metamétodos que vale la pena conocer:
__add,__sub,__mul,__div— aritmética__eq,__lt,__le— comparación__tostring— representación de cadena__index— acceso a un campo inexistente__newindex— registro de un nuevo campo__call— llamada de la tabla como función__len- redefinición del operador#
Con __call se puede hacer una tabla de llamadas, y esto se usa realmente en producción:
local Logger = setmetatable({}, {
__call = function(self, message)
print("[LOG] " .. os.date("%H:%M:%S") .. " — " .. message)
end
})
Logger("Server is running") -- [LOG] 14:32:01 — Сервер запущенPatrones prácticos: tablas en código real
Configuración a través de la tabla
local config = {
server = {
host = "localhost",
port = 8080,
},
database = {
name = "myapp",
user = "admin",
password = "hunter2", -- классика
},
debug = true,
}
print(config.server.port) -- 8080Conjunto (Set)
local function Set(list)
local set = {}
for _, v in ipairs(list) do
set[v] = true
end
return set
end
local langs = Set{"Lua", "Python", "JavaScript", "Lua"}
if langs["Lua"] then
print("Lua in action!") -- Lua в деле!
end
if not langs["COBOL"] then
print("COBOL? No, we haven't heard of it")
endCola
local Queue = {}
Queue.__index = Queue
function Queue.new()
return setmetatable({first = 1, last = 0}, Queue)
end
function Queue:push(value)
self.last = self.last + 1
self[self.last] = value
end
function Queue:pop()
if self.first > self.last then return nil end
local value = self[self.first]
self[self.first] = nil
self.first = self.first + 1
return value
end
local q = Queue.new()
q:push("first")
q:push("second")
print(q:pop()) -- "first"
print(q:pop()) -- "second"Principales errores de los principiantes con las tablas
1. Olvidar que las tablas se comparten a través de un enlace
local a = {1, 2, 3}
local b = a -- b указывает на ту же таблицу!
b[1] = 999
print(a[1]) -- 999 (сюрприз!)¿Quieres una copia? Hazlo a mano:
local function shallowCopy(t)
local copy = {}
for k, v in pairs(t) do
copy[k] = v
end
return copy
end2. Confundir pairs e ipairs
ipairs— solo claves numéricas, en orden, se detiene en la primeranilpairs— todas las claves, el orden no está garantizado
3. Modificar la tabla durante la iteración
No lo hagas así. Simplemente no lo hagas. Recopila los cambios en una tabla separada y luego aplícalos.
4. Considerar # fiable para tablas con agujeros
Ya lo hemos dicho, pero lo repetiremos: nil en el medio de la matriz = longitud impredecible. Sin opciones.
¡Aprende Lua y otros idiomas con Kodik!
Si has leído hasta aquí, claramente estás interesado no solo en la teoría, sino también en la práctica. Las tablas en Lua se aprenden mejor cuando escribes el código a mano, no solo lees artículos.
Kodik es una aplicación en la que puedes aprender programación desde cero y mejorar tus habilidades a través de tareas prácticas. Python, JavaScript, HTML, CSS y otras tecnologías, todo con el objetivo de que realmente escribas código, no solo lo mires.
Y también tenemos Canal de Telegram con una comunidad de más de 2000 desarrolladores, donde se publican regularmente publicaciones útiles, análisis de tareas y memes sobre programación (no se puede vivir sin ellos). Una excelente manera de repetir el material en un lugar cómodo: en la cola, en el transporte, durante el almuerzo. Suscríbete y mejora cada día.
En resumen: ¿por qué las tablas son geniales?
Las tablas en Lua son una navaja suiza que al principio parece extraña, pero luego no entiendes cómo has podido vivir sin ella. Una estructura de datos en lugar de diez, un mínimo de sintaxis, un máximo de flexibilidad.
Esto es lo que vale la pena recordar:
Las tablas reemplazan matrices, diccionarios, objetos, clases y todo en general
La indexación con 1 no es un error, sino una característica (solo acéptalo)
Las metatablas convierten las tablas en un sistema de objetos completo
Las tablas se transmiten a través de un enlace: ten cuidado al copiarlas
#funciona de forma fiable solo para matrices sin agujeros
Lua es un lenguaje que demuestra que menos es más. Y las tablas son el mejor ejemplo de esta filosofía.
Ahora ve y escribe algo en Lua. Las tablas te están esperando. 🚀
