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 let
não precisa cobrir todas as ramificações. Isso pode torná-lo mais conciso do quematch
. - Um uso comum é lidar com valores
Some
ao trabalhar-se comOption
. - Ao contrário de
match
,if let
não suporta cláusulas de guarda para correspondência de padrões.
let-else
if-let
s 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 let
continuará executando enquanto o valor corresponder ao padrão. - Você pode reescrever o loop
while let
como um loop infinito com uma instruçãoif
que é interrompido quando não houver mais nenhum valor para unwrap (desempacotar) paraname.pop()
. Owhile let
fornece um atalho para o cenário acima.