Controle de Fluxo Let
Rust possui algumas construções de fluxo de controle que diferem de outras linguagens. Elas são usadas para correspondência de padrões:
- Expressões
if let - Expressões
let else - Expressões
while let
Expressões if let
A expressão if let lhe permite executar um código diferente caso um valor corresponde a um padrão:
use std::time::Duration; fn sleep_for(secs: f32) { if let Ok(dur) = Duration::try_from_secs_f32(secs) { std::thread::sleep(dur); println!("dormiu por {:?}", dur); } } fn main() { sleep_for(-10.0); sleep_for(0.8); }
Expressões let else
Para o caso comum de corresponder a um padrão e retornar da função, use let else. O caso “else” deve divergir (return, break ou pânico - qualquer coisa, exceto cair no final do bloco).
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("obteve None")); }; let first_byte_char = if let Some(first_byte_char) = s.chars().next() { first_byte_char } else { return Err(String::from("obteve uma string vazia")); }; if let Some(digit) = first_byte_char.to_digit(16) { Ok(digit) } else { Err(String::from("não é um dígito hexadecimal")) } } fn main() { println!("result: {:?}", hex_or_die_trying(Some(String::from("foo")))); }
Similar a if let, há uma variante while let que testa repetidamente se um valor corresponde a um padrão:
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!) }
Aqui String::pop retorna Some(c) até que a string esteja vazia e depois ela retornará None. O while let nos permite iterar por todos os itens.
if-let
- Ao contrário de
match,if letnão precisa cobrir todas as ramificações. Isso pode torná-lo mais conciso do quematch. - Um uso comum é lidar com valores
Someao trabalhar-se comOption. - Ao contrário de
match,if letnão suporta cláusulas de guarda para correspondência de padrões.
let-else
if-lets podem se acumular, como mostrado. A construção let-else permite o “achatamento” desse código aninhado. Reescreva a versão “estranha” para os alunos, para que eles possam ver a transformação.
A versão reescrita é:
#![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("obteve None")); }; let Some(first_byte_char) = s.chars().next() else { return Err(String::from("obteve uma string vazia")); }; let Some(digit) = first_byte_char.to_digit(16) else { return Err(String::from("não é um dígito hexadecimal")); }; return Ok(digit); } }
while-let
- Ressalte que o loop
while letcontinuará executando enquanto o valor corresponder ao padrão. - Você pode reescrever o loop
while letcomo um loop infinito com uma instruçãoifque é interrompido quando não houver mais nenhum valor para unwrap (desempacotar) paraname.pop(). Owhile letfornece um atalho para o cenário acima.