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.