Traits de Extensão e Iterador
Traits de extensão adicionam métodos a tipos existentes (str, Iterator, tipos de terceiros) sem encapsulamento. Adaptadores de iterador compõem pipelines de dados de custo zero.
Receita
trait IterExt: Iterator {
fn collect_vec(self) -> Vec<Self::Item> where Self: Sized { self.collect() }
}
impl<I: Iterator> IterExt for I {}Quando usar isso: Auxiliares ergonômicos em tipos que você não possui; utilitários de iterador reutilizáveis.
Exemplo de Trabalho
trait StrExt {
fn trimmed_nonempty(&self) -> Option<&str>;
}
impl StrExt for str {
fn trimmed_nonempty(&self) -> Option<&str> {
let t = self.trim();
if t.is_empty() { None } else { Some(t) }
}
}
let ids: Vec<u64> = records.iter().filter_map(|r| r.id).collect();O que isso demonstra:
- Padrão de trait de extensão + implementação genérica (blanket impl)
- Cadeias de iterador são preguiçosas até
collect/sum - Prefira adaptadores padrão (
filter_map,try_fold) antes dos customizados - Mantenha traits de extensão no módulo
preludedo seu crate
Mergulho Profundo
Implementações genéricas (Blanket impls): impl<T: AsRef<str>> StrExt for T {} para cobertura mais ampla. Para iteradores, Iterator::map + collect é melhor que loops manuais, a menos que perfilado.
Armadilhas
- Regra do órfão em tipos estrangeiros - não é possível implementar um trait estrangeiro para um tipo estrangeiro. Correção: trait de extensão que você possui.
- Colisões de nomes - métodos entram em conflito com futuras adições do padrão. Correção: prefixe métodos ou use módulos.
- Iteradores excessivamente customizados - reinventando
filter. Correção: use adaptadores padrão. - Coleta sem tipo - falhas de inferência. Correção:
collect::<Vec<_>>()ou turbofish. - Iterador de referências clonadas - alocações ocultas. Correção:
copied()para itensCopy.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Funções livres | Não precisa de ergonomia de método | Deseja API fluente |
| Newtype de wrapper | Muitos métodos em um tipo | Único auxiliar em str |
crate itertools | Adaptadores ricos | Simples linha única padrão |
FAQs
Extensão vs. inerente?
Inerente no seu tipo; extensão para outros que você não pode modificar.
itertools quando?
tuple_windows, intersperse - adicione dependência quando o padrão for insuficiente.
iteração assíncrona?
StreamExt de futures para pipelines assíncronos.
implementação genérica órfã?
Seu trait + sua implementação genérica em tipo estrangeiro é permitido.
nomeação de métodos?
Evite nomes semelhantes aos do padrão que possam conflitar posteriormente.
desempenho?
Adaptadores de iterador são de custo zero em release quando inlined.
try_fold?
Processamento de Result com interrupção sem coletar e depois validar.
encadear Option?
into_iter() em Option produz 0-1 itens.
Polars preguiçoso?
Modelo de iterador diferente; use a API de expressão do Polars, não IterExt manual.
testar iteradores?
Assert em collect::<Vec<_>>() para cadeias de adaptadores.
Relacionado
- Abstrações de Custo Zero
- Noções Básicas de Padrões Rust
- Padrões de Closure de Iterador
- Anti-Padrões Comuns
Versões da Pilha: 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+.