Ir al contenido principal

Bucles

En ocasiones necesitamos hacer algunas tareas repetitivas y necesitamos que el programa ejecute una serie de instrucciones repetidamente. Para este tipo de necesidad existen los bucles, que ejecutan una serie de instrucciones de manera repetida hasta que se detengan en base a una condición. Esta condición debe cumplirse para que empiecen a ejecutarse y seguirán haciéndolo mientras esta condición sea válida. En el momento en que la condición ya no sea válida el bucle se detiene.

Los ciclos de funcionamiento de un bucle se llaman iteraciones. Una iteración empieza con la verificación de la condición y si esta es true, se ejecuta el bloque de código. Las iteraciones se repiten hasta que la condición sea false. Sin embargo, existe una excepción que veremos a continuación.

Lua ofrece los siguientes tipos de bucles:

Tipo de bucleDescripción
whileEl bucle while define una condición y un bloque de código
forEl bucle for define una secuencia y un bloque de código
repeatEl bucle repeat es similar al bucle while pero invertido

Todos los bucles en Lua se pueden anidar, esto es, que pueden ponerse bucles dentro de otros bucles, para construir así operaciones más complejas.


Bucle while

El bucle while es el más polivalente de todos los bucles. Acepta una condición de cualquier tipo permitiendo mucha flexibilidad a la hora de controlarlo. Este tipo de bucle se puede ejecutar cero o más veces.

La sintaxis de un bucle while es:

while(condition)
do
    -- Instrucciones
end

A continuación se muestra un ejemplo de bucle while:

i = 1

while(i <= 10)
do
    print(i)
    i = i + 1
end

Que produce la siguiente salida:

1
2
3
4
5
6
7
8
9
10

Bucle for

El bucle for está especializado en la iteración de tablas y secuencias. Permite principalmente definir el número de veces que el bucle debe ejecutarse. El bucle for puede ejecutarse cero o más veces.

La sintaxis del bucle for es:

for inicializacion, objetivo, incremento
do
    -- Instrucciones
end

Veamos en más detalle los tres componentes que debemos definir en el bucle for:

  • inicializacion: se define una variable de control a la cual se le dará un valor numérico inicial. Esta inicialización se realiza una sola vez. Esta variable será utilizada para llevar el control del número de iteraciones.
  • objetivo: es el valor máximo o mínimo que la variable de control puede alcanzar. El bucle se ejecutará hasta que la variable de control alcance el máximo o el mínimo definido.
  • incremento: indica en cuantas unidades se debe incrementar la variable de control. Este incremento ocurre después de cada iteración.

En el bucle for, cuando se ejecuta la primera iteración, se realiza la inicialización de la variable de control. Luego se verifica que la variable de control no es igual al valor máximo/mínimo y si es diferente se ejecutan las instrucciones. Al finalizar el bloque de instrucciones, se incrementa la variable de control con el valor definido en incremento. En las siguientes iteraciones, se vuelve a comprobar la variable de control con el objetivo, si aun no ha sido alcanzado, se vuelven a ejecutar las instrucciones y se vuelve a incrementar la variable de control. Estas iteraciones se repetirán hasta que la variable de control tenga el mismo valor que el objetivo definido. Todas estas operaciones son realizadas por el intérprete automáticamente.

En el siguiente ejemplo se imprime una lista de números del 1 al 10:

i = 1
for i = 1, 10, 1
do
    print(i)
end

El resultado del ejemplo anterior es:

1
2
3
4
5
6
7
8
9
10

Bucle repeat

A diferencia de los bucles while o for, el bucle repeat...until ejecuta el bloque de instrucciones al menos una vez, siempre antes de verificar la condición. Una vez ejecutado el bloque de instrucciones se verifica la condición, si esta es false, se vuelve a ejecutar el bloque de instrucciones, si es true, la ejecución finaliza.

El bucle repeat...until es similar al bucle while, la única diferencia es que el bucle repeat...until verifica la condición después de ejecutar el bloque de código.

La sintaxis del bucle repeat...until es:

repeat
    -- Instrucciones
until(condiciones)

Como puedes observar en el ejemplo anterior, la expresión condicional se encuentra después del bloque de instrucciones, de este modo el bloque de instrucciones siempre se ejecuta al menos una vez antes de que se verifique la condición.

Un ejemplo de uso del bucle repeat...until es el siguiente:

mensajes = {}

repeat
  if (#(mensajes) == 0) then
      print("No hay mensajes")
  else
      print(table.remove(mensajes, 1))
  end
until(#(mensajes) == 0)

El resultado del ejemplo anterior es:

No hay mensajes

Como ves, el bloque de código se ha ejecutado una sola vez, ya que la tabla mensajes está vacía. Probemos ahora con algunos mensajes:

mensajes = {
  "Mensaje 1",
  "Mensaje 2",
  "Mensaje 3"
}

repeat
  if (#(mensajes) == 0) then
    print("No hay mensajes")    
  else        
    print(table.remove(mensajes, 1))
  end
until(#(mensajes) == 0)

Cuyo resultado es:

Mensaje 1
Mensaje 2
Mensaje 3

En este caso ya no aparece No hay mensajes. Al ejecutarse el bloque de instrucciones mensajes tiene una longitud de 3, con lo que se extrae el primer elemento de la lista y se imprime (Mensaje 1). Durante la verificación de la condición, esta no se cumple porque mensajes tiene una longitud de 2. El bloque se ejecuta una vez más, extrayendo el primer elemento de la lista. Al comprobar la condición, mensajes tiene una longitud de 1, con lo que no se cumple y la ejecución continua. El bloque se ejecuta de nuevo, extrae el primer elemento de la lista y lo imprime. Durante la verificación de la condición, esta vez mensajes tiene una longitud de 0, por lo que el bucle finaliza.

Bucles anidados

El anidamiento de bucles permite la realización de tareas complejas, como por ejemplo, el recorrido de arrays multidimensionales. Cuando anidamos bucles, lo podemos hacer con cualquier tipo de bucle, pudiendo mezclarlos si es preciso.

A continuación se muestran algunos ejemplos:

-- Bucle while anidado en un bucle for

for indice, valor, incremento
do
  while(condicion)
  do
    -- instrucciones
  end
  
  -- instrucciones
end
-- Bucle while anidado en bucle while

while(condicion)
do
  while(condicion)
  do
    -- instrucciones
  end
  
  -- instrucciones
end
-- Bucle for anidado en otro bucle for

for indice, valor, incremento
do
  for indice, valor, incremento
  do
    -- instrucciones
  end
  -- instrucciones
end

Instrucción break

La instrucción break permite controlar la ejecución del bucle. Con ella podemos finalizar el bucle en todo momento, sin que sea necesario que la condición se cumpla.

Cuando el intérprete encuentra una instrucción break dentro de un bucle, sale del bucle y continua ejecutando las instrucciones siguientes. Si el la instrucción break se encuentra dentro de un bucle anidado, la ejecución pasará al bucle padre.

El siguiente ejemplo muestra el funcionamiento de la instrucción break:

print("Antes del bucle")

for i = 1, 5, 1
do
  if (i > 3) then
    break
  end

  print("-> " .. i)

  for j = 1, 5, 1
  do
    if (j > 3) then
      break
    end

    print("   |- " .. j)
  end
end

print("Despues del bucle")

Al ejecutar el código anterior obtenemos el siguiente resultado:

Antes del bucle
--> 
|- 1
|- 2
|- 3
--> 2
|- 1
|- 2
|- 3
--> 3
|- 1
|- 2
|- 3
Despues del bucle

Observa como el uso de la instrucción break nos ha permitido modificar el funcionamiento del bucle. En lugar de imprimir hasta el número 5, que es el máximo en ambos bucles, hemos puesto una condición que sale del bucle cuando llega a 3. Cuando esto sucede en el bucle anidado, la ejecución continua en el bucle padre. Cuando el bucle padre llega a 3, finaliza y continua con la última instrucción del ejemplo.

Bucle infinito

Un bucle es infinito cuando la condición es siempre válida. Sirve generalmente para casos en los que se necesita que el bucle se ejecute continuamente como base del funcionamiento del programa. Para ello se usa generalmente el bucle while al que le ponemos como condición la palabra clave true, de este modo forzamos que la condición sea siempre válida. Un ejemplo de bucle infinito es:

while(true)
do
 -- instrucciones
end

Siempre puedes finalizar el bucle en todo momento con la instrucción break.