Fn, FnMut & FnOnce
Closures implementam Fn (empréstimo compartilhado), FnMut (empréstimo mutável) ou FnOnce (consome capturas) com base no uso.
Receita
fn call_twice(f: impl Fn() -> i32) -> i32 {
f() + f()
}
fn main() {
let n = 10;
println!("{}", call_twice(|| n));
}Quando usar: Limitar parâmetros de closure em APIs genéricas (thread::spawn precisa de FnOnce).
Exemplo de Trabalho
fn with_mut(f: impl FnMut(&mut Vec<i32>)) {
let mut v = vec![1];
f(&mut v);
}
fn main() {
with_mut(|v| v.push(2));
}O que isto demonstra:
FnMutpara modificar estado capturado ou argumentos de referência mutável.FnOncenecessário se a closure consumir umaStringcapturada.- O compilador escolhe a implementação mínima do trait.
Mergulho Profundo
Fn é um subtrait de FnMut, que é um subtrait de FnOnce. Prefira impl Fn quando possível para flexibilidade.
Armadilhas
spawnrequerFnOnce + Send + 'static: Capturas devem ser de propriedade. Correção: closuremove.- Armazenar objeto de trait
FnMut:Box<dyn FnMut()>. Correção: Box ou genérico. - Chamar
FnOnceduas vezes: Erro de compilação. Correção: Chamar uma vez ou clonar os dados antes. - Capturas conflitantes: Mover e emprestar a mesma variável. Correção: Reestruturar capturas.
- Referências de método em closure: A implementação automática do trait pode ser
FnMut.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
Ponteiro de função fn() | Sem captura | Necessita de ambiente |
Genérico F: FnOnce | Callback flexível | Necessita de vetor homogêneo de callbacks |
Box<dyn FnMut()> | Armazenamento em tempo de execução | Monomorfização é aceitável |
FAQs
Qual trait é escolhido?
O compilador analisa as capturas e as chamadas.dyn Fn?
Object safe para chamadas compartilhadas.closure async?
Closures async do Rust 1.85+ estão evoluindo - verifique a edição.Hierarquia do trait Fn?
Fn implica FnMut implica FnOnce.thread spawn?
FnOnce + Send + 'static.closure sort_by?
FnMut comparando elementos.Iterator map?
FnMut por elemento.Capturas de cópia?
Tipos `move` ou `Copy` capturados por valor.closure RefCell?
Empréstimo `FnMut` de `RefCell`.test?
Assertar a contagem de chamadas com `Cell`.Relacionados
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+.