Iteradores en Lua
Los iteradores son construcciones del lenguaje que nos permiten recorrer los elementos de una tabla de manera ordenada y sencilla. Piensa en un iterador como un ayudante que va extrayendo, uno por uno, todos los elementos que guardaste en una caja (tabla), para que puedas examinarlos o trabajar con ellos.
El uso más común de los iteradores es dentro de los bucles for, donde nos facilitan enormemente la tarea de procesar cada elemento de una tabla sin tener que preocuparnos de llevar la cuenta manualmente de las posiciones o claves.
¿Cómo funcionan los iteradores?
El principio es muy simple: en cada vuelta del bucle for, el iterador se encarga de devolver el siguiente elemento de la tabla. Cuando ya no quedan más elementos, el iterador devuelve nil y el bucle termina automáticamente.
Veamos un ejemplo básico para entenderlo mejor:
paises = {"España", "Francia", "Italia", "Portugal"}
for indice, valor in ipairs(paises) do
print(indice, valor)
end
Si ejecutamos este código, obtenemos:
1 España
2 Francia
3 Italia
4 Portugal
Como puedes ver, el iterador ipairs() nos ha devuelto, en cada iteración, dos valores: el índice (posición) del elemento y su valor.
Iteradores genéricos en Lua
Lua incluye dos iteradores genéricos en su librería estándar que cubren la mayoría de las necesidades básicas:
ipairs(): para recorrer arrays (tablas con índices numéricos)pairs(): para recorrer diccionarios (tablas con claves de cualquier tipo)
Veamos cada uno en detalle.
El iterador ipairs()
El iterador ipairs() está diseñado específicamente para recorrer arrays, es decir, tablas cuyos elementos están indexados numéricamente. Su nombre viene de "integer pairs" (pares de enteros).
Características de ipairs():
- Recorre los elementos en orden secuencial
- Devuelve el índice numérico y el valor de cada elemento
- Garantiza el orden de iteración
- Se detiene al encontrar el primer
nilo hueco en la secuencia
Veamos un ejemplo práctico:
frutas = {"manzana", "naranja", "plátano", "pera", "uva"}
print("Listado de frutas:")
for i, fruta in ipairs(frutas) do
print("Posición " .. i .. ": " .. fruta)
end
Resultado:
Listado de frutas:
Posición 1: manzana
Posición 2: naranja
Posición 3: plátano
Posición 4: pera
Posición 5: uva
Si no necesitas el índice, puedes usar un guion bajo _ para indicar que no lo vas a utilizar:
for _, fruta in ipairs(frutas) do
print("Me gusta la " .. fruta)
end
El iterador pairs()
El iterador pairs() es más versátil y puede recorrer cualquier tipo de tabla, tanto arrays como diccionarios (tablas con claves no numéricas).
Características de pairs():
- Puede recorrer tablas con cualquier tipo de clave
- No garantiza un orden específico de iteración para diccionarios
- Devuelve la clave (de cualquier tipo) y el valor
- Para arrays, se comporta similar a
ipairs()pero con orden garantizado
Ejemplo con un diccionario:
parametros = {
host = "localhost",
puerto = 5432,
usuario = "admin",
basedatos = "mibd"
}
print("Configuración:")
for clave, valor in pairs(parametros) do
print(clave .. " = " .. valor)
end
Posible resultado (el orden puede variar):
Configuración:
usuario = admin
puerto = 5432
basedatos = mibd
host = localhost
Como puedes observar, los elementos no se han mostrado en el orden en que los definimos. Esto es normal con pairs() cuando trabajamos con diccionarios.
Ejemplo con un array usando pairs()
colores = {"rojo", "verde", "azul", "amarillo"}
for indice, color in pairs(colores) do
print("Color " .. indice .. ": " .. color)
end
Resultado:
Color 1: rojo
Color 2: verde
Color 3: azul
Color 4: amarillo
Para arrays, pairs() sí mantiene el orden secuencial.
Comparación entre ipairs() y pairs()
Veamos un ejemplo comparativo para entender mejor las diferencias:
-- Array de países
paises = {"Suiza", "España", "Colombia", "Italia", "Francia"}
-- Diccionario de configuración
config = {
idioma = "español",
tema = "oscuro",
notificaciones = true
}
-- Usando ipairs() con el array
print("=== Usando ipairs() con array ===")
for i, pais in ipairs(paises) do
print(i, pais)
end
-- Usando pairs() con el array
print("\n=== Usando pairs() con array ===")
for i, pais in pairs(paises) do
print(i, pais)
end
-- Usando ipairs() con el diccionario
print("\n=== Usando ipairs() con diccionario ===")
for clave, valor in ipairs(config) do
print(clave, valor)
end
-- No imprime nada porque ipairs() no funciona con diccionarios
-- Usando pairs() con el diccionario
print("\n=== Usando pairs() con diccionario ===")
for clave, valor in pairs(config) do
print(clave, valor)
end
Resultado:
=== Usando ipairs() con array ===
1 Suiza
2 España
3 Colombia
4 Italia
5 Francia
=== Usando pairs() con array ===
1 Suiza
2 España
3 Colombia
4 Italia
5 Francia
=== Usando ipairs() con diccionario ===
=== Usando pairs() con diccionario ===
tema oscuro
idioma español
notificaciones true
Conclusiones de la comparación:
- Con arrays, tanto
ipairs()comopairs()funcionan bien ipairs()no puede iterar diccionarios (tablas con claves no numéricas)pairs()funciona con cualquier tipo de tabla- Para arrays, ambos mantienen el orden; para diccionarios,
pairs()no garantiza orden
¿Cuándo usar cada iterador?
La elección del iterador depende del tipo de tabla que estés manejando:
Usa ipairs() cuando:
- Trabajas con arrays (listas secuenciales)
- Necesitas garantizar el orden de iteración
- El índice numérico es importante para tu lógica
- Quieres que el bucle se detenga al encontrar el primer
nil
Usa pairs() cuando:
- Trabajas con diccionarios (tablas con claves no numéricas)
- Las claves no son números
- No te importa el orden de iteración
- Necesitas recorrer todos los pares clave-valor sin importar su tipo
Casos de uso prácticos
Calcular el total de una lista de precios
precios = {15.50, 23.00, 8.75, 42.30, 19.99}
total = 0
for _, precio in ipairs(precios) do
total = total + precio
end
print("Total: " .. total .. " euros")
Validar configuración de usuario
configuracion = {
nombre = "Ana García",
edad = 28,
email = "ana@ejemplo.com",
activo = true
}
print("Validando configuración:")
for campo, valor in pairs(configuracion) do
if valor == nil or valor == "" then
print("ERROR: El campo " .. campo .. " está vacío")
else
print("OK: " .. campo .. " = " .. tostring(valor))
end
end
Buscar un elemento en una lista
usuarios = {"pedro", "maria", "juan", "laura", "carlos"}
buscar = "juan"
encontrado = false
for i, usuario in ipairs(usuarios) do
if usuario == buscar then
print("Usuario encontrado en la posición " .. i)
encontrado = true
break
end
end
if not encontrado then
print("Usuario no encontrado")
end
Crear un menú interactivo
opciones = {
"Ver perfil",
"Editar datos",
"Cambiar contraseña",
"Cerrar sesión"
}
print("=== MENÚ PRINCIPAL ===")
for num, opcion in ipairs(opciones) do
print(num .. ". " .. opcion)
end
print("\nSelecciona una opción (1-" .. #opciones .. "):")
Errores comunes al usar iteradores
Error 1: Usar ipairs() con diccionarios
-- ❌ INCORRECTO
datos = {nombre = "Juan", edad = 30}
for i, v in ipairs(datos) do -- No imprime nada
print(i, v)
end
-- ✓ CORRECTO
for clave, valor in pairs(datos) do
print(clave, valor)
end
Error 2: Modificar la tabla durante la iteración
-- ⚠️ CUIDADO: esto puede dar resultados inesperados
numeros = {1, 2, 3, 4, 5}
for i, num in ipairs(numeros) do
if num % 2 == 0 then
table.remove(numeros, i) -- Modifica la tabla que estamos iterando
end
end
Es mejor crear una nueva tabla con los elementos que quieres mantener:
-- ✓ MEJOR PRÁCTICA
numeros = {1, 2, 3, 4, 5}
impares = {}
for _, num in ipairs(numeros) do
if num % 2 ~= 0 then
table.insert(impares, num)
end
end
Error 3: Asumir orden con pairs() en diccionarios
-- El orden puede variar en cada ejecución
puntuaciones = {juan = 100, ana = 95, pedro = 87}
-- No asumas que siempre se imprimirán en el mismo orden
for nombre, puntos in pairs(puntuaciones) do
print(nombre .. ": " .. puntos)
end
Resumen
Los iteradores son herramientas fundamentales en Lua que simplifican enormemente el trabajo con tablas:
- ipairs() es tu mejor opción para arrays y listas secuenciales
- pairs() es versátil y funciona con cualquier tipo de tabla
- Los iteradores manejan automáticamente el recorrido y la detención del bucle
- Elegir el iterador correcto hace tu código más claro y eficiente
En próximos artículos exploraremos conceptos más avanzados como la creación de iteradores personalizados, pero con ipairs() y pairs() ya tienes las herramientas necesarias para la mayoría de situaciones cotidianas en tus programas Lua.