Ir al contenido

While en Rust

Un bucle while sigue ejecutándose mientras una condición sea true. Es la herramienta adecuada cuando sabes qué estás esperando, aunque no sepas exactamente cuántas vueltas hará falta dar.

fn main() {
let mut count = 1;
while count <= 5 {
println!("{count}");
count += 1;
}
}

Salida:

1
2
3
4
5
▶ Pruébalo tú mismo

La condición (count <= 5) se comprueba antes de cada vuelta del bucle. En cuanto es false, el bucle termina; aquí, cuando count llega a 6.

Podrías escribir lo mismo con loop y un if/break a mano, pero while expresa lo que quieres decir de forma más directa: “sigue mientras esto sea verdad”. Reserva loop para los casos en que la condición de parada no encaja de forma natural al principio del bucle.

// con while: claro y al grano
let mut n = 0;
while n < 3 {
println!("{n}");
n += 1;
}
// lo mismo con loop: funciona, pero hay más que leer
let mut n = 0;
loop {
if n >= 3 {
break;
}
println!("{n}");
n += 1;
}

while es habitual para cosas como esperar a que un valor llegue a un objetivo:

fn main() {
let mut balance = 100;
while balance < 200 {
balance += 25;
println!("Ahora el saldo es {balance}");
}
println!("¡Objetivo alcanzado!");
}

Salida:

Ahora el saldo es 125
Ahora el saldo es 150
Ahora el saldo es 175
Ahora el saldo es 200
¡Objetivo alcanzado!
▶ Pruébalo tú mismo

La condición puede ser cualquier expresión que dé un bool, así que puedes combinar comprobaciones con && y ||, que viste en la página de Operadores, como en while balance < 200 && months < 12.

Algunos lenguajes tienen un bucle do { ... } while (condición). Ejecuta el cuerpo primero y comprueba la condición después, así que el cuerpo siempre se ejecuta al menos una vez. Rust no lo tiene. En su lugar, usas loop y pones la comprobación al final.

Veamos un caso en el que esto importa. Para contar las cifras de un número, puedes dividirlo entre 10 una y otra vez hasta que no quede nada. Pero el número 0 también tiene una cifra, y un bucle while normal no llega a ejecutarse con él:

fn main() {
let number = 0;
// Un bucle while comprueba primero, así que con 0 nunca se ejecuta.
let mut n = number;
let mut digits = 0;
while n > 0 {
digits += 1;
n /= 10;
}
println!("según while, {number} tiene {digits} cifras");
// loop + una comprobación al final ejecuta el cuerpo al menos una vez.
let mut n = number;
let mut digits = 0;
loop {
digits += 1;
n /= 10;
if n == 0 {
break;
}
}
println!("según loop, {number} tiene {digits} cifra");
}

Salida:

según while, 0 tiene 0 cifras
según loop, 0 tiene 1 cifra
▶ Pruébalo tú mismo

Cambia number a 4096 y las dos versiones coinciden: 4 cifras. La diferencia solo aparece cuando la condición es falsa desde el principio. Así que la regla práctica es: si el cuerpo tiene que ejecutarse al menos una vez, escribe loop con el if ... { break; } al final.

Hay un tipo más de bucle while, while let, que sigue repitiendo mientras un valor encaje con un patrón. Lo verás en la página de If Let y While Let.

Suma 1 + 2 + 3 + … y para en cuanto el total sea mayor que 100. Imprime cuántos números sumaste y el total. Pista: necesitas dos variables mut: una para el siguiente número y otra para el total.

Ver solución
fn main() {
let mut next = 1;
let mut total = 0;
while total <= 100 {
total += next;
next += 1;
}
println!("Sumé {} números y el total es {total}", next - 1);
}

Salida:

Sumé 14 números y el total es 105
▶ Pruébalo tú mismo

Después de la última vuelta, next ya avanzó un paso de más; por eso imprimimos next - 1. Vale la pena comprobar estos detalles de “uno de más o uno de menos” con un ejemplo pequeño en la cabeza.

Empieza con 1000. Mientras el número sea mayor que 1, divídelo entre 2 (división entera) e imprímelo. Al final, imprime cuántas divisiones hicieron falta. Pista: n /= 2 divide n entre 2 y descarta el resto.

Ver solución
fn main() {
let mut n = 1000;
let mut steps = 0;
while n > 1 {
n /= 2;
steps += 1;
println!("{n}");
}
println!("Hicieron falta {steps} divisiones para llegar a 1");
}

Salida:

500
250
125
62
31
15
7
3
1
Hicieron falta 9 divisiones para llegar a 1
▶ Pruébalo tú mismo

125 / 2 da 62, no 62.5, porque los dos números son enteros. Eso es lo que hace que el bucle termine justo en 1.

  • while condición { ... } repite mientras la condición sea true, y la comprueba antes de cada vuelta.
  • Asegúrate de que algo dentro del bucle acabe haciendo que la condición sea false, o se ejecutará para siempre.
  • Prefiere while a loop siempre que la condición de parada encaje de forma natural como “mientras se cumpla X”.
  • Rust no tiene do-while. Cuando el cuerpo tenga que ejecutarse al menos una vez, usa loop con la comprobación del break al final.

Comprueba lo aprendido

1. ¿Cuál es el error clásico que provoca un bucle while infinito?

2. Según esta página, ¿cuándo conviene usar while en lugar de loop?

3. ¿Cómo escribes un bucle cuyo cuerpo se ejecute siempre al menos una vez?

Puntuación: 0 / 3