- Rust 100%
| .woodpecker | ||
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| LICENSE | ||
| README.md | ||
Lição 33: Funções Anônimas (Closures)
1. Narrativa
O piloto do mecha Æther cria protocolos rápidos em tempo real — closures são funções anônimas que capturam o ambiente ao redor. Diferente de funções nomeadas, closures podem acessar variáveis do escopo onde são criadas, tornando-as perfeitas para protocolos de resposta imediata no cockpit.
2. Conceito
Closures são funções anônimas que capturam seu ambiente:
- Sintaxe:
|parametros| corpo— ex:|x| x * 2 Fn: Captura por referência imutável — pode ser chamada múltiplas vezesFnMut: Captura por referência mutável — pode modificar estado internoFnOnce: Captura por posse (ownership) — só pode ser chamada uma vezmove: Força captura por ownership — necessário ao retornar closures- Retorno:
impl Fn(T) -> U— retornar closures de funções
3. Requisitos
- Criar closures básicas sem captura
- Capturar variáveis do ambiente com
move - Usar
RefCellpara estado mutável em closuresFnMut - Passar closures como parâmetros e retorná-las de funções
🔭 Referência futura: Esta lição usa
std::cell::RefCellpara obter mutabilidade interior dentro de uma closureFnMut.RefCellé uma "smart pointer" com check de borrow em runtime — o detalhamento completo vem na Lição 037 (Tipos Box) e em Lição 043 (Estado Compartilhado). Aqui basta saber:RefCell<T>::borrow_mut()devolve uma referência mutável verificada em runtime (pânico se houver conflito de borrow) eborrow()devolve uma imutável. A regra doRefCellé a mesma do borrow checker, só que aplicada em tempo de execução.Também usamos métodos de iterators (como
dados.sum()emconsumir_recurso) para agregar os dados capturados pela closure. O detalhamento completo de iterators e seus adaptadores vem na Lição 034 (Iterators) — aqui basta saber que.sum()consome o iterator e soma todos os elementos.
4. Design de Dados
graph LR
A["Fn: |x| x * 2"] --> B["Sem captura"]
C["Fn: move |x| x + base"] --> D["Captura por valor imutável"]
E["FnMut: RefCell + move"] --> F["Estado mutável interno"]
G["FnOnce: move || dados.sum()"] --> H["Consome dados"]
I["Parâmetro: impl Fn(i32) -> i32"] --> J["Closure como argumento"]
5. Diagrama de Fluxo
flowchart TD
A[Início] --> B{Tipo de closure?}
B -->|Leitura| C["Fn — captura &T"]
B -->|Modificação| D["FnMut — captura &mut T"]
B -->|Consumo| E["FnOnce — captura T"]
C --> F["Pode chamar múltiplas vezes"]
D --> G["Precisa ser mut para chamar"]
E --> H["Só pode chamar uma vez"]
F --> I[Retornar closure com impl Fn]
G --> I
H --> I
6. Funções
| Função | Descrição |
|---|---|
criar_dobrador |
Closure Fn sem captura: ` |
calibrar_com_base |
Closure Fn com captura move: soma base |
gerar_acumulador |
Closure FnMut com RefCell: acumula estado |
consumir_recurso |
Closure FnOnce: consome Vec e soma |
aplicar_protocolo |
Recebe closure como parâmetro |
criar_filtro |
Retorna closure que filtra por limiar |
7. Exemplo
let dobrador = criar_dobrador();
assert_eq!(dobrador(5), 10);
let calibrar = calibrar_com_base(100);
assert_eq!(calibrar(50), 150);
let mut acum = gerar_acumulador(0);
assert_eq!(acum(10), 10);
assert_eq!(acum(5), 15);
let filtro = criar_filtro(50);
assert!(filtro(60));
assert!(!filtro(30));
8. Missão
- Implementar
criar_dobrador— closure pura sem captura, traitFn - Implementar
calibrar_com_base— captura commove, traitFn - Implementar
gerar_acumulador—RefCellpara mutabilidade interna, traitFnMut - Implementar
consumir_recurso— consome dados, traitFnOnce - Implementar
aplicar_protocolo— closure como parâmetro comimpl Fn - Implementar
criar_filtro— closure como retorno com captura emove
9. Como Executar
cargo build
cargo test
cargo clippy -- -D warnings
cargo fmt --check
10. Dicas
- Toda
FnOnceé tambémFnMuteFn— o inverso não é verdade moveé necessário ao retornar closures de funções — sem ele, as variáveis capturadas seriam droppingRefCell<T>permite mutabilidade interior em contextoFn— segurança em runtime (ver Lições 037 e 043 para o detalhamento completo)impl Fn(T) -> Uno retorno permite devolver closures sem nomear o tipo exato