Control de Flujo Let
Rust tiene algunas construcciones de control de flujo que difieren de otros lenguajes. Se utilizan para el patrón de coincidencia:
- Expresiones
if let - Expresiones
let else - Expresiones
while let
Expresiones if let
La [expresión if let][(https://doc.rust-lang.org/reference/expressions/if-expr.html#if-let-expressions) te permite ejecutar código diferente en función de si un valor coincide con un patrón:
use std::time::Duration;
fn sleep_for(secs: f32) {
if let Ok(dur) = Duration::try_from_secs_f32(secs) {
std::thread::sleep(dur);
println!("Horas de sueño: {:?}", dur);
}
}
fn main() {
sleep_for(-10.0);
sleep_for(0.8);
}
Expresiones let else
En el caso habitual de coincidencia con un patrón y retorno de la función, utiliza let else. El caso “else” debe divergir (return, break o pánico; cualquier acción es válida menos colocarlo al final del bloque).
fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> {
let s = if let Some(s) = maybe_string {
s
} else {
return Err(String::from("se ha obtenido None"));
};
let first_byte_char = if let Some(first_byte_char) = s.chars().next() {
first_byte_char
} else {
return Err(String::from("se ha encontrado una cadena vacía"));
};
if let Some(digit) = first_byte_char.to_digit(16) {
Ok(digit)
} else {
Err(String::from("no es un dígito hexadecimal"))
}
}
fn main() {
println!("resultado: {:?}", hex_or_die_trying(Some(String::from("foo"))));
}
Al igual que con if let, hay una variante while let que prueba repetidamente un valor con respecto a un patrón:
fn main() {
let mut name = String::from("Comprehensive Rust 🦀");
while let Some(c) = name.pop() {
println!("character: {c}");
}
// (There are more efficient ways to reverse a string!)
}
Aquí, String::pop devolverá Some(c) hasta que la cadena este vacía, cuando empezara a devolver None. while let nos permite seguir iterando a través de todos los elementos.
if-let
- A diferencia de
match,if letno tiene que cubrir todas las ramas, pudiendo así conseguir que sea más conciso quematch. - Un uso habitual consiste en gestionar valores
Someal trabajar conOption. - A diferencia de
match,if letno admite cláusulas guardia para la coincidencia de patrones.
let-else
Las instrucciones if-let se pueden apilar, tal y como se muestra. La construcción let-else permite aplanar este código anidado. Reescribe esta rara versión para que los participantes puedan ver la transformación.
La versión reescrita es la siguiente:
#![allow(unused)]
fn main() {
fn hex_or_die_trying(maybe_string: Option<String>) -> Result<u32, String> {
let Some(s) = maybe_string else {
return Err(String::from("se ha obtenido None"));
};
let Some(first_byte_char) = s.chars().next() else {
return Err(String::from("se ha encontrado una cadena vacía"));
};
let Some(digit) = first_byte_char.to_digit(16) else {
return Err(String::from("no es un dígito hexadecimal"));
};
return Ok(digit);
}
}
while-let
- Señala que el bucle
while letseguirá funcionando siempre que el valor coincida con el patrón. - Puedes reescribir el bucle
while letcomo un ciclo infinito con una instrucción if que rompe el bucle siname.pop()no devuelve un valor para desenvolver.while letproporciona azúcar sintáctico para la situación anterior.