{}const=>[]async()letfn</>var
DesarrolloLua

Tablas en Lua: la estructura más poderosa que los principiantes subestiman

Entendemos por qué las tablas, la única estructura de datos en Lua, no son una limitación, sino un superpoder. Matrices, diccionarios, objetos, clases e incluso colas: todas son tablas. Con ejemplos de código, metatablas, errores típicos de los principiantes y memes.

К

Kodik

Autor

8 min de lectura

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.

🔥 100.000+ estudiantes ya están con nosotros

¿Cansado de leer teoría?
¡Hora de programar!

Kodik — una app donde aprendes a programar con práctica. Mentor IA, lecciones interactivas, proyectos reales.

🤖 IA 24/7
🎓 Certificados
💰 Gratis
🚀 Empezar
Se unieron hoy

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. JavaScript

ipairs — 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
end

Tabla 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)  -- 8080

Conjunto (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")
end

Cola

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
end

2. Confundir pairs e ipairs

  • ipairs — solo claves numéricas, en orden, se detiene en la primera nil

  • pairs — 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. 🚀

🎯Deja de postergar

¿Te gustó el artículo?
¡Hora de practicar!

En Kodik no solo lees — escribes código de inmediato. Teoría + práctica = habilidades reales.

Práctica instantánea
🧠IA explica código
🏆Certificado

Sin registro • Sin tarjeta