if let, let else & while let
Essas construções correspondem a um padrão quando um match completo é pesado. let else fornece retorno antecipado em caso de incompatibilidade.
Receita
fn main() {
let v = Some(10);
if let Some(n) = v {
println!("{n}");
}
let Some(n) = v else {
panic!("esperava Some");
};
println!("forçado {n}");
}Quando usar isso: Desembrulhar opcional, loop até None e cláusulas de guarda com let else.
Exemplo de Trabalho
use std::collections::VecDeque;
fn drain_even(q: &mut VecDeque<i32>) -> Vec<i32> {
let mut out = Vec::new();
while let Some(&front) = q.front() {
if front % 2 == 0 {
out.push(q.pop_front().unwrap());
} else {
break;
}
}
out
}
fn main() {
let mut q = VecDeque::from([2, 4, 5, 6]);
println!("{:?}", drain_even(&mut q));
}O que isso demonstra:
while letitera enquanto o padrão corresponde- Combina com
breakquando a condição muda if letpara um único caso de ramificaçãolet elsepara padrão obrigatório (Rust 1.65+)
Mergulho Profundo
if let
if let Err(e) = result {
eprintln!("{e}");
}let else
fn head(s: &str) -> &str {
let Some((h, _)) = s.split_once(' ') else {
return s;
};
h
}O bloco else deve divergir (return, break, panic).
while let
Ideal para consumir iteradores de Option ou Result até que None/Err quebre o padrão.
Armadilhas
- O bloco
elsedelet elsedeve divergir - Não pode cair. Correção:return/break/panic!. - Movendo em
if let- Vincula a movimentação a menos queref. Correção:if let Some(ref x). while letinfinito se o padrão sempre corresponder - Bug lógico. Correção: Garanta que o iterador avance ou o estado mude.- Encadear muitos
if let- Difícil de ler. Correção: Usematchou métodos combinadores. if let+elsenão é substituto completo paramatch- Apenas um braço positivo é ergonômico. Correção:matchpara muitos braços.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
match | Múltiplos braços | Caminho de sucesso único |
Option::map / and_then | Transformar opcional | Efeitos colaterais em ramificações |
? em Option em fn | Propagar ausência | Em main sem retorno de fn |
unwrap_or / unwrap_or_else | Valor padrão | Lógica de ramificação complexa |
FAQs
`if let` vs `match`?
Use `if let` para um padrão; `match` para muitos.Pode `let else` atribuir?
Sim - vincula variáveis de padrão no escopo externo após o sucesso.`while let` consumir iterador?
Chame `next()` dentro do padrão: `while let Some(x) = it.next()`.Múltiplos padrões?
`if let (Some(a), Some(b)) = (oa, ob)` com padrões de tupla.Mudanças na Edição 2024?
Modos de vinculação podem afetar mover/copiar em padrões - verifique as notas de migração.`else if let`?
Encadeamento suportado: `if let A(a) = x { } else if let B(b) = x { }`.Let refutável?
Apenas `let else` ou match - `let` simples deve ser irrefutável.`while let` assíncrono?
Funciona com streams assíncronos usando padrões `.next().await`.Lint para `unwrap`?
Clippy `manual_unwrap_or_default` etc. sugerem idiomas.Loops GUI/eventos?
`while let` comum para processamento de fila de eventos.Relacionados
Versões do Stack: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.