Los bucles son estructuras de control que permiten ejecutar un bloque de código repetidas veces. Su función principal es automatizar tareas repetitivas, permitiéndote procesar colecciones de datos o esperar a que se cumpla una condición específica sin escribir código redundante. Usas un for cuando sabes exactamente cuántas veces quieres iterar, un for-in cuando quieres recorrer cada elemento de una lista, o un while cuando la repetición depende de una condición lógica que puede cambiar en cualquier momento. Si no defines correctamente la condición de salida, puedes crear un bucle infinito, lo que congelará la ejecución de tu programa al consumir todos los recursos del procesador.
Para controlar el flujo dentro de estos bucles, dispones de break, que detiene el bucle por completo, y continue, que salta la iteración actual y pasa a la siguiente. En casos de bucles anidados (un bucle dentro de otro), puedes usar labels (etiquetas) para indicar exactamente qué bucle quieres interrumpir o saltar. Una distinción vital es la diferencia entre el bucle for-in y el método .forEach(). Mientras que for-in es una estructura de lenguaje que permite usar break y continue, .forEach() es un método que recibe una función anónima; por lo tanto, intentar usar break dentro de un .forEach() provocará un error de sintaxis porque estarías intentando romper el bucle desde el contexto de una función, no desde el cuerpo del bucle mismo.
void main() {
// 1. El bucle for clásico: ideal para contadores
print('--- For clásico ---');
for (int i = 1; i <= 3; i++) {
print('Contador: $i');
}
// 2. For-in: la forma más limpia de iterar colecciones
print('\n--- For-in con control de flujo ---');
final frutas = ['manzana', 'banana', 'cereza', 'dátil'];
for (final fruta in frutas) {
if (fruta == 'cereza') {
print('Saltando la cereza con continue...');
continue; // Salta a la siguiente iteración
}
if (fruta == 'dátil') {
print('Encontré el dátil, saliendo con break.');
break; // Rompe el bucle por completo
}
print('Fruta actual: $fruta');
}
// 3. While y Do-While
print('\n--- While y Do-While ---');
int intentos = 0;
while (intentos < 2) {
print('While: intento $intentos');
intentos++;
}
int cuenta = 0;
do {
print('Do-while: ejecución $cuenta');
cuenta++;
} while (cuenta < 2); // Se garantiza al menos una ejecución
// 4. Bucles anidados con labels
print('\n--- Bucle anidado con label ---');
exterior: // Definición de la etiqueta
for (int x = 1; x <= 3; x++) {
for (int y = 1; y <= 3; y++) {
if (x == 2 && y == 2) {
print('Condición crítica: rompiendo bucle exterior...');
break exterior;
}
print('Coordenada: x=$x, y=$y');
}
}
// 5. Collection for [disponible desde Dart 2.3]
// Genera una nueva lista transformando elementos de otra
print('\n--- Collection for ---');
final numerosOriginales = [1, 2, 3, 4, 5];
final duplicados = [for (final n in numerosOriginales) n * 2];
print('Lista duplicada: $duplicados');
}
En el código anterior, el bucle for clásico utiliza un inicializador (int i = 1), una condición de parada (i <= 3) y un incremento (i++) para controlar el flujo. Cuando usamos for (final fruta in frutas), el motor de Dart accede directamente al iterador de la colección frutas. Fíjate cómo continue permite que la iteración de la cereza se ignore, pero el bucle sigue vivo, mientras que break termina el ciclo en cuanto detecta el dátil.
En la sección de bucles anidados, la etiqueta exterior: permite que el comando break exterior; no solo rompa el bucle interno de y, sino que detenga también el bucle de x. Sin la etiqueta, el break solo afectaría al bucle más cercano. Finalmente, la técnica de collection for es una característica de azúcar sintáctico muy potente de Dart que permite construir listas de forma declarativa, aplicando la lógica del bucle directamente dentro de los corchetes de la lista duplicados.
El error frecuente
Un error clásico al trabajar con bucles while es olvidar actualizar la variable que controla la condición. Si la condición siempre es verdadera, el programa entrará en un bucle infinito:
void errorInfinito() {
int contador = 0;
// Si olvidas el contador++, este bucle nunca terminará
while (contador < 5) {
print('Esto se imprimirá eternamente: $contador');
// Falta: contador++;
}
}
Este comportamiento bloquea el hilo de ejecución actual, lo que en una aplicación de consola detendrá el proceso y en un servidor podría consumir la CPU de forma desmedida.
N° 21