Un bucle en programación es una estructura de control que hace que un bloque de código se ejecute varias veces. La mayoría de los lenguajes de programación tienen bucles. A menudo se declaran con las instrucciones for, while o repeat.

El bloque de código que se debe repetir se llama cuerpo del bucle (o ciclo). Puede contener prácticamente cualquier código que el desarrollador necesite. La propia estructura de control describe cuánto tiempo deben repetirse las acciones: se puede establecer una cantidad clara de repeticiones o hacer que el bucle se ejecute hasta que se alcance una determinada condición.

La cantidad de veces que se ejecutará un bucle depende de sus condiciones y de la tarea. Hay bucles que no pueden ejecutarse ni una sola vez, y otros que pasan cientos de iteraciones, incluso hasta el infinito. A veces esto es un error, a veces es el comportamiento esperado.

Diagrama de flujo que muestra la estructura básica de un bucle de programación con una condición y un cuerpo de bucle.
Estructura de un bucle en programación.

¿Quién y por qué utiliza bucles?

Los bucles se encuentran en el trabajo de la mayoría de los programadores en prácticamente todos los lenguajes de programación. Están en Java, JavaScript, PHP, Python, C++: en todas partes. Los bucles en su forma habitual solo no están presentes en lenguajes de muy bajo nivel, cercanos al «hardware», como el ensamblador.

Se utilizan bucles para tareas en las que es necesario repetir la misma acción varias veces. Hay muchas tareas de este tipo en el desarrollo. Por ejemplo:

  • Contar datos de un archivo línea por línea;
  • Procesar cada elemento de una estructura de datos por turno;
  • Modificar una serie de datos;
  • Resolver un problema matemático;
  • Actualizar la pantalla.

Algunos algoritmos son iterativos, es decir, funcionan con varias iteraciones (repeticiones). Para implementarlos, normalmente se necesitan bucles.

Una alternativa parcial a los bucles en la programación puede ser algunas funciones integradas de orden superior. Pueden realizar varias acciones, por ejemplo, con una matriz. Pero estas funciones no existen en todos los lenguajes y no son adecuadas para todo. Los bucles son más versátiles.

Tipos de Bucles

Normalmente, los lenguajes de programación tienen varios tipos de bucles. Cada uno tiene su propósito. Vamos a ver los principales.

For

Este es un bucle que se ejecuta una cantidad determinada de veces. En la mayoría de los lenguajes similares a C (es decir, aquellos que son externamente similares a C y C++) tiene una estructura similar:

for (<declaración de variable>; <condición>; <acción>) {
  <subprograma>
}

La declaración de variable es la creación de un iterador, una variable que cambiará en cada paso del bucle. Cuando el iterador alcance un cierto valor, el bucle terminará.

La condición describe si el bucle debe continuar. Mientras se cumpla, el bucle funciona. La condición suele ser que el iterador sea menor o mayor que un número determinado. En consecuencia, cuando el iterador alcanza el valor especificado, el bucle se detiene.

La acción es lo que se debe realizar al final de cada iteración. Aquí se registran los cambios del iterador: por ejemplo, agregarle una unidad o restarle un número.

Diagrama que muestra las tres partes principales de un bucle for: inicialización, condición y expresiones al final del bucle.
Funcionamiento de un bucle for.

Un caso estándar: se establece un iterador igual a 0. La condición es que el iterador sea menor que un cierto N. La acción es agregarle una unidad al iterador. El bucle se ejecutará N+1 veces, porque el conteo comienza desde cero. También hay variaciones, que veremos más adelante.

En algunos lenguajes, como Python o Pascal, la sintaxis del bucle for es diferente. Pero la esencia es la misma: se utiliza cuando se conoce de antemano la cantidad de acciones necesarias.

For in / for of / for-each

Un caso particular del bucle for es cuando se necesita recorrer una estructura de datos. Para ello, algunos lenguajes tienen una construcción especial. Este es un bucle for que, en lugar de un iterador, trabaja con la propia estructura de datos, por ejemplo, una matriz u objeto.

En JavaScript, este bucle se llama for of (también existe for in, pero funciona un poco diferente), en Java es for-each, en Python es for in. La sintaxis es aproximadamente la siguiente:

for <iterador> in* <estructura de datos> {
  <subprograma>
}

in se proporciona como ejemplo. En JS no es in, sino of, y en Java y C++ es un dos puntos.

Este bucle se ejecutará una cantidad determinada de veces, exactamente tantas como elementos haya en la estructura de datos. Y el iterador en cada paso será igual al elemento actual en la estructura o a su número. Esto depende del lenguaje y de la construcción elegida.

Este enfoque es conveniente, ya que permite describir de forma más concisa y clara el trabajo con matrices y otras estructuras de datos.

No debe confundirse este bucle con la función forEach(). Recorre una matriz y hace algo con cada uno de sus elementos. Pero no es un bucle, sino una de las funciones de orden superior de las que hablamos anteriormente.

While con pre-condición

While es un caso completamente diferente. Es un bucle que se utiliza si se desconoce de antemano la cantidad de acciones necesarias. Puede ejecutarse varias veces, una vez, un número infinito de veces, o no ejecutarse ni una sola vez. La palabra while se traduce como «mientras» y refleja la esencia: mientras sea cierta una determinada condición, se ejecuta el bucle.

Su sintaxis es aproximadamente la siguiente, aunque dependiendo del lenguaje los detalles pueden variar:

while (<condición>) {
  <subprograma>
}

Parece más simple que for, y a veces se utiliza como alternativa. Pero la esencia de este bucle es diferente. Por ejemplo, no sabemos de antemano cuántos pasos tendremos que dar para implementar un algoritmo iterativo. En estos casos es necesario while.

While con post-condición

Esta es una variación del bucle while. Su única diferencia es que la condición no se escribe antes, sino después del cuerpo del bucle:

do {
  <subprograma>
} while (<condición>);

La condición se comprobará cuando el subprograma ya se haya ejecutado. Además, este bucle siempre se ejecutará al menos una vez, antes de comprobar la condición. Se utiliza con menos frecuencia que while con pre-condición, pero a veces esta construcción resulta útil.

Dos diagramas de flujo comparan las estructuras de bucle while y do-while, mostrando la diferencia en la posición de la verificación de la condición.
Bucles while y do-while: Precondición vs. Postcondición.

Repeat / until

En algunos lenguajes existe otro tipo de bucle: repeat o until. Es similar a while, pero a diferencia de él, describe no la condición para continuar, sino la condición para salir del bucle. El bucle terminará cuando la condición sea verdadera.

En Pascal es un bucle con post-condición, que se describe así:

repeat {
  <subprograma>
} until (<condición>);

Y, por ejemplo, en Perl es un bucle con pre-condición:

until (<condición>) {
  <subprograma>
}

Este tipo de bucle no ha tenido éxito en el desarrollo y se encuentra con bastante poca frecuencia. En la mayoría de los lenguajes no existe. Pero es conveniente recordarlo si desea programar en lenguajes donde existe dicha construcción.

Modificación de Bucles

Un bucle estándar por contador o condición se puede modificar. Esto rara vez es necesario en el desarrollo comercial, pero puede ser útil para implementar algoritmos.

Bucle por estructura de datos

Este es el bucle for in / for of del que ya hemos hablado. Con un bucle normal también se puede recorrer una matriz: iniciar un contador desde 0 hasta la longitud de la estructura de datos. Pero hay detalles que deben aclararse con más detalle.

La estructura de datos debe ser iterable. Esta es una propiedad de algunas entidades en la programación: indica que el contenido de la entidad se puede enumerar. Los objetos iterables tienen un iterador interno: un puntero que sirve para la enumeración.

Si la estructura no es iterable, normalmente no se puede recorrer con un bucle for in / for of. En la mayoría de los lenguajes de programación funciona así.

Se puede hacer que una estructura sea iterable: escribir su propio iterador o adjuntar uno estándar. Esta posibilidad existe en la mayoría de los lenguajes de programación y ayuda a controlar finamente la iteración de las estructuras de datos.

Bucle inverso

Aquí todo es más sencillo: el bucle for se puede iniciar no solo desde 0 hasta un cierto número, sino también al revés. Entonces, el iterador en cada paso no aumentará, sino que disminuirá en una unidad. En consecuencia, el bucle se ejecutará la misma cantidad de veces, pero en dirección inversa. A veces esta posibilidad resulta útil.

Por cierto, invertir el bucle for no es la única modificación que se puede hacer. Se puede, por ejemplo, hacer un bucle con un paso de 2 o más, para que el iterador no cambie en 1, sino en 2 u otro número. Se puede incluso no sumar ni restar números, sino multiplicar o dividir. Hay muchas variaciones. Pero no se utilizan con tanta frecuencia para no complicar el código: una buena práctica es hacer que el programa sea claro y fácil de leer.

Bucle anidado

A veces se le llama bucle doble. Es un bucle dentro del cual se anida otro bucle. Con mayor frecuencia es un bucle for.

El cuerpo del bucle externo es el bucle interno. Y dentro ya pueden haber diferentes subprogramas.

Diagrama de flujo que ilustra la estructura de un bucle anidado, mostrando un bucle principal que contiene otro bucle.
Funcionamiento de un bucle anidado en programación.

Los bucles anidados se pueden utilizar, por ejemplo, para cálculos en estructuras de datos bidimensionales: matrices, tensores. Pero en general, se considera que si se puede evitar el uso de bucles anidados, es mejor hacerlo.

En cada paso del bucle externo se ejecuta todo el bucle interno, completamente. Si el bucle externo se produce N veces y el interno M veces, la cantidad total de iteraciones en el bucle anidado es N * M. Esto es mucho. Por lo tanto, los bucles anidados consumen muchos recursos, y se utilizan solo si no se puede prescindir de ellos. Además, la construcción de dos bucles uno dentro del otro complica seriamente la legibilidad del código.

Bucle infinito

Si en un bucle no hay una condición de salida, el subprograma que contiene se repetirá infinitamente. Terminará solo si se interrumpe la ejecución de todo el código.

Un bucle while suele volverse infinito, pero en teoría, también se puede hacer un bucle for infinito, por ejemplo, si no se cambia el iterador o si se establece una condición de salida imposible.

A menudo, un bucle infinito es un error de los programadores principiantes, que describen incorrectamente la condición. Pero hay situaciones en las que la repetición infinita es el modo de funcionamiento estándar. Por ejemplo, un programa en un bucle infinito actualiza la imagen en la pantalla cada pocos milisegundos: esto terminará solo si se sale de él.

Cómo interrumpir un bucle

Existen varias maneras de detener la ejecución de un bucle. Con mayor frecuencia se utiliza la que la propia construcción prevé: la no ejecución de la condición. Pero también hay otras posibilidades. Utilizarlas no siempre es correcto.

No cumplimiento de la condición

La opción más frecuente: la condición para continuar el bucle ya no se cumple. El iterador ha alcanzado el valor necesario, o se ha encontrado la variable que se buscaba. Entonces, el bucle se termina y el programa comienza a ejecutar el código que se escribió después de él.

Las condiciones pueden ser diferentes, incluso complejas, que constan de varias partes. A continuación, hablaremos sobre break y continue: en la mayoría de los casos, las condiciones correctamente formuladas ayudan a prescindir del uso de estos operadores.

Omitir una iteración

Si por alguna razón en un bucle es necesario terminar una iteración antes de tiempo y pasar a la siguiente, existe un comando especial para ello. Normalmente se llama continue. En esencia, es un operador que le dice al programa: «Termina esta repetición, continúa con el siguiente paso».

Continue debe escribirse simplemente en el lugar donde desee salir de la iteración actual, por ejemplo, si se ha cumplido una determinada condición en el programa.

En la práctica, continue no se utiliza demasiado a menudo, en muchos lenguajes se considera una mala práctica. Se puede reemplazar con un operador condicional.

Salir del bucle

Se puede salir de un bucle de forma abrupta en cualquier momento. Para ello, en muchos lenguajes de programación existe el comando break. Significa «Interrumpe la ejecución del subprograma y sal de él».

Cuando el programa llega a este comando, sale del bucle o condición y comienza a ejecutar el código que sigue. Ya no se producen más iteraciones. Por ejemplo, estábamos buscando un número en un bucle, lo encontramos: no es necesario seguir recorriendo el bucle. Se puede salir de él.

El uso de break para salir de los bucles también se considera una mala práctica en la mayoría de los lenguajes de programación. Se cree que este operador viola la regularidad y la lógica del funcionamiento del programa, haciendo que el código sea más difícil de depurar. Por lo tanto, no se recomienda utilizarlo sin necesidad extrema.

El comando se puede utilizar no solo en bucles, sino también, por ejemplo, en estructuras condicionales if/else.

Pausa

Algunos lenguajes permiten pausar temporalmente un bucle, como si se estableciera un retraso para su ejecución. Por ejemplo, esperar unos segundos: para ello existen funciones especiales. Cómo implementar dicha posibilidad depende del lenguaje y de la situación.

Consideraciones al usar bucles

En algunos lenguajes, se suele utilizar bucles solo si no hay alternativas. Esto se debe a las peculiaridades del enfoque de la programación. Por ejemplo, en JavaScript se considera una buena práctica utilizar funciones de orden superior para procesar matrices siempre que sea posible, y recurrir a los bucles solo si no hay otra manera.

Los bucles, especialmente los anidados, consumen muchos recursos. Son menos intensivos en recursos que la recursividad, pero si se resuelve una tarea de forma no óptima, se puede perder mucha memoria. Esto debe tenerse en cuenta al implementar algoritmos.

Utilizar los operadores break y continue sin necesidad es una mala práctica en la mayoría de los lenguajes de programación. Violan la estructura del programa, hacen que el código sea menos lógico y predecible.

Al utilizar bucles, debe vigilarse la corrección de la descripción y el cálculo del iterador. De lo contrario, existe el riesgo de obtener un bucle infinito o que no funcione correctamente.

Categorizado en:

Fundamentos,