Condicionales y Bucles
Aprende el control de flujo con if/else, loop, while, for y la expresión match
Condicionales y Bucles
Rust proporciona control de flujo familiar con algunos giros únicos. Todas las construcciones de control de flujo son expresiones que pueden devolver valores.
if / else if / else
A diferencia de C, las condiciones no necesitan paréntesis:
fn main() {
let numero = 7;
if numero < 5 {
println!("pequeño");
} else if numero < 10 {
println!("mediano");
} else {
println!("grande");
}
}if es una Expresión
Todo bloque if/else devuelve un valor — ambos brazos deben ser del mismo tipo:
fn main() {
let condicion = true;
let numero = if condicion { 5 } else { 6 };
println!("{numero}"); // 5
// ERROR: los brazos deben ser del mismo tipo
// let malo = if condicion { 5 } else { "seis" };
}fn main() {
let x = 10;
let resultado = if x > 5 {
"mayor"
} else if x == 5 {
"igual"
} else {
"menor"
};
println!("{resultado}"); // "mayor"
}loop — Bucles Infinitos
loop se ejecuta para siempre a menos que se salga explícitamente:
fn main() {
let mut contador = 0;
let resultado = loop {
contador += 1;
if contador == 10 {
break contador * 2; // Break con un valor
}
};
println!("resultado: {resultado}"); // 20
}Etiquetas de Bucle
Las etiquetas permiten salir de bucles anidados:
fn main() {
'externo: for i in 1..=3 {
for j in 1..=3 {
if i == 2 && j == 2 {
break 'externo; // Sale de ambos bucles
}
println!("({i}, {j})");
}
}
}| Característica | Sintaxis | Propósito |
|---|---|---|
| Etiqueta | 'nombre: | Nombrar un bucle |
| Break con valor | break valor | Salir y devolver valor |
| Continue | continue | Saltar a siguiente iteración |
| Break etiquetado | break 'nombre | Salir del bucle externo |
Usa loop cuando necesites patrones "reintentar hasta éxito" o salir con un valor. Para iteración contada, prefiere for.
while — Bucles Condicionales
fn main() {
let mut n = 3;
while n > 0 {
println!("{n}");
n -= 1;
}
println!("¡lanzamiento!");
}while también puede ser una expresión con break:
fn main() {
let mut n = 0;
let resultado = while n < 10 {
n += 1;
if n == 7 {
break n;
}
};
println!("primero >= 7: {resultado:?}"); // Some(7)
}El valor de break de un bucle while es Option<T> porque la condición puede nunca ser verdadera. En loop, el valor de break es T directamente.
for — Iteración
for es el bucle preferido en Rust — es seguro, rápido y expresivo:
fn main() {
// Sintaxis de rango
for i in 0..5 { // 0, 1, 2, 3, 4
print!("{i} ");
}
println!();
// Rango inclusivo
for i in 0..=5 { // 0, 1, 2, 3, 4, 5
print!("{i} ");
}
println!();
// Iterar sobre colección
let arr = [10, 20, 30];
for elemento in arr {
print!("{elemento} ");
}
println!();
// Con índice (enumerate)
for (indice, valor) in arr.iter().enumerate() {
println!("arr[{indice}] = {valor}");
}
}Patrones de Iteración
fn main() {
// Rango inverso
for i in (1..=5).rev() {
print!("{i} "); // 5 4 3 2 1
}
println!();
// Paso a paso
for i in (0..10).step_by(2) {
print!("{i} "); // 0 2 4 6 8
}
println!();
// Sobre caracteres de una cadena
for ch in "hola".chars() {
print!("{ch} ");
}
println!();
}| Tipo de Bucle | Cuándo Usar | Break Devuelve |
|---|---|---|
loop | Necesita salir con valor, o indefinido | T |
while | Basado en condición, verificado cada iteración | Option<T> |
for | Iterar sobre colección o rango | Option<T> |
Match — Coincidencia de Patrones
match es el poderoso switch de Rust mejorado. Es exhaustivo — cada caso posible debe ser manejado:
fn main() {
let numero = 3;
match numero {
1 => println!("uno"),
2 => println!("dos"),
3 => println!("tres"),
_ => println!("otro"), // Caso comodín
}
}_ es el patrón comodín. Coincide con cualquier cosa y es el caso por defecto. El compilador advierte si lo olvidas y no has cubierto todos los valores.
Match como Expresión
fn main() {
let valor = 7;
let descripcion = match valor {
0 => "cero",
1..=3 => "pequeño", // Patrón de rango
4..=6 => "mediano",
7..=9 => "grande",
_ if valor > 100 => "enorme", // Condición de guardia
_ => "otro",
};
println!("{descripcion}"); // "grande"
}Match con Enums
enum Moneda {
Centavo,
CincoCentavos,
DiezCentavos,
VeinticincoCentavos,
}
fn valor_en_centavos(moneda: Moneda) -> u8 {
match moneda {
Moneda::Centavo => 1,
Moneda::CincoCentavos => 5,
Moneda::DiezCentavos => 10,
Moneda::VeinticincoCentavos => 25,
}
}Match con Option
fn main() {
let algun_valor: Option<i32> = Some(10);
let doblado = match algun_valor {
Some(x) => x * 2,
None => 0,
};
println!("{doblado}"); // 20
}if let — Coincidencia Concisa
Cuando solo te importa un patrón:
fn main() {
let config_max = Some(3u8);
// Match verboso
match config_max {
Some(max) => println!("max: {max}"),
_ => (),
}
// if let conciso
if let Some(max) = config_max {
println!("max: {max}");
}
// if let con else
let valor: Option<i32> = None;
if let Some(x) = valor {
println!("recibió {x}");
} else {
println!("no recibió nada");
}
}| Construcción | Mejor Para |
|---|---|
match | Verificación exhaustiva, 3+ brazos |
if let | Un patrón para coincidir, ignorar el resto |
let else | Desenvolver o retornar/salir temprano |
let-else (Rust 1.65+)
fn main() {
let valor: Option<i32> = Some(42);
let Some(x) = valor else {
println!("sin valor");
return;
};
println!("recibió {x}");
}Mundo Real: Validación de Entrada
use std::io;
fn main() {
let mut entrada = String::new();
println!("Ingresa un número entre 1 y 10:");
io::stdin().read_line(&mut entrada).unwrap();
let numero: i32 = match entrada.trim().parse() {
Ok(n) => n,
Err(_) => {
println!("¡Número inválido!");
return;
}
};
match numero {
1..=5 => println!("{numero} está en la mitad inferior"),
6..=10 => println!("{numero} está en la mitad superior"),
_ => println!("{numero} está fuera del rango"),
}
}Preguntas de Práctica
- ¿Puedes usar
ifsinelseen Rust? - ¿Qué hace
break 42dentro de unloop? - ¿Qué tipo devuelve un bucle
whilecuando se interrumpe con un valor? - ¿Cómo iterar sobre un array con índice y valor?
- ¿Qué sucede si un
matchno cubre todos los valores posibles? - ¿Cuál es la diferencia entre
0..5y0..=5? - ¿Cuándo usar
if leten lugar dematch? - ¿Qué hace el patrón
_en una expresión match? - ¿Cómo difiere
let-elsedeif let? - Escribe un bucle for que imprima números del 10 al 1.