<h2>O que são Closures em Rust?</h2>
<p>Closures são funções anônimas que podem capturar variáveis do escopo ao seu redor. Diferente de funções regulares, closures mantêm referências ou propriedade das variáveis externas, permitindo um padrão funcional poderoso. Em Rust, o tipo de closure é determinado automaticamente pelo compilador baseado em como ele usa as variáveis capturadas. A distinção entre <code>Fn</code>, <code>FnMut</code> e <code>FnOnce</code> é fundamental para entender como closures interagem com a memória e o ownership do Rust.</p>
<p>O sistema de traits de closures foi projetado para oferecer máxima flexibilidade mantendo segurança de memória. Quando você cria um closure, o compilador analisa quais variáveis são capturadas e como são usadas, determinando automaticamente qual trait implementar. Esta análise acontece em tempo de compilação, não em runtime, garantindo zero overhead e máxima otimização.</p>
<h2>Entendendo os Três Traits: Fn, FnMut e FnOnce</h2>
<h3>Fn — Apenas Leitura</h3>
<p><code>Fn</code> é o trait mais restritivo. Closures que implementam <code>Fn</code> podem ser chamados múltiplas vezes e apenas leem as variáveis capturadas sem modificá-las ou consumi-las. O closure recebe referências imutáveis (<code>&T</code>) das variáveis externas.</p>
<pre><code class="language-rust">fn main() {
let multiplier = 5;
let multiply = |x| x * multiplier; // Captura multiplier como &i32
println!("{}", multiply(3)); // 15
println!("{}", multiply(4)); // 20
// Pode ser chamado infinitas vezes
let result: Vec<i32> = vec![1, 2, 3]
.iter()
.map(|&x| multiply(x))
.collect();
}</code></pre>
<h3>FnMut — Leitura e Escrita</h3>
<p><code>FnMut</code> permite que o closure modifique as variáveis capturadas, mas não as consome. Recebe referências mutáveis (<code>&mut T</code>). Pode ser chamado múltiplas vezes, mas não simultaneamente em diferentes threads de forma segura.</p>
<pre><code class="language-rust">fn main() {
let mut counter = 0;
let mut increment = || {
counter += 1; // Modifica counter
counter
};
println!("{}", increment()); // 1
println!("{}", increment()); // 2
println!("{}", increment()); // 3
// Passando FnMut para uma função
apply_twice(&mut increment);
}
fn apply_twice<F>(f: &mut F)
where
F: FnMut(),
{
f();
f();
}</code></pre>
<h3>FnOnce — Consumo Total</h3>
<p><code>FnOnce</code> consome as variáveis capturadas, transferindo sua propriedade para dentro do closure. Pode ser chamado apenas uma vez. Use quando o closure precisa tomar posse dos dados capturados.</p>
<pre><code class="language-rust">fn main() {
let name = String::from("Rust");
let greeting = || {
println!("Olá, {}", name); // Consome name
};
greeting(); // Primeira chamada
// greeting(); // Erro: já foi consumido
// Exemplo com uma thread
let value = String::from("dados importantes");
std::thread::spawn(move || {
println!("Thread usa: {}", value); // move transfere propriedade
}).join().unwrap();
// println!("{}", value); // Erro: value foi movido
}</code></pre>
<h2>Hierarquia e Coerção de Traits</h2>
<p>Existe uma relação hierárquica entre estes traits: todo <code>Fn</code> é também <code>FnMut</code>, e todo <code>FnMut</code> é também <code>FnOnce</code>. Isto significa que você pode passar um <code>Fn</code> onde <code>FnMut</code> ou <code>FnOnce</code> é esperado, mas não o contrário.</p>
<pre><code class="language-rust">fn execute_fn<F>(f: F)
where
F: Fn(i32) -> i32,
{
println!("Resultado: {}", f(5));
}
fn execute_fn_mut<F>(mut f: F)
where
F: FnMut(i32) -> i32,
{
println!("Primeiro: {}", f(5));
println!("Segundo: {}", f(10));
}
fn main() {
let add_three = |x| x + 3; // Implementa Fn
execute_fn(add_three); // OK: Fn pode ser usado como Fn
execute_fn_mut(add_three); // OK: Fn pode ser usado como FnMut
let mut sum = 0;
let adder = |x| {
sum += x; // Implementa FnMut
sum
};
execute_fn_mut(adder); // OK: FnMut pode ser usado como FnMut
// execute_fn(adder); // Erro: FnMut não pode ser Fn
}</code></pre>
<h2>Casos Práticos de Uso</h2>
<p>Closures são essenciais para padrões funcionais e callbacks em Rust. A escolha do trait correto impacta a flexibilidade e performance do seu código. Iteradores usam closures extensivamente: <code>map</code> requer <code>Fn</code>, enquanto <code>for_each</code> permite <code>FnMut</code>.</p>
<pre><code class="language-rust">fn main() {
let numbers = vec![1, 2, 3, 4, 5];
let multiplier = 10;
// map usa Fn — não modifica estado externo
let doubled: Vec<i32> = numbers
.iter()
.map(|x| x * multiplier)
.collect();
let mut total = 0;
// for_each usa FnMut — pode modificar total
numbers.iter().for_each(|&x| {
total += x;
});
println!("Somados: {}", total); // 15
// Processando Strings com FnOnce
let process_data = |data: String| {
data.to_uppercase()
};
let result = process_data(String::from("rust"));
println!("{}", result); // RUST
}</code></pre>
<h2>Conclusão</h2>
<p>Os três traits de closures em Rust — <code>Fn</code>, <code>FnMut</code> e <code>FnOnce</code> — refletem diferentes níveis de controle sobre dados capturados. <strong>Primeiro aprendizado</strong>: escolha <code>Fn</code> quando apenas ler variáveis; <code>FnMut</code> quando modificá-las; <code>FnOnce</code> quando consumir. <strong>Segundo aprendizado</strong>: esta hierarquia não é apenas sintaxe, mas um reflexo direto do sistema de ownership, oferecendo segurança em tempo de compilação. <strong>Terceiro aprendizado</strong>: dominar estes conceitos abre as portas para programação funcional elegante em Rust, essencial para iteradores, threads e APIs modernas.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://doc.rust-lang.org/book/ch13-01-closures.html" target="_blank" rel="noopener noreferrer">The Rust Book — Closures</a></li>
<li><a href="https://doc.rust-lang.org/rust-by-example/fn/closures.html" target="_blank" rel="noopener noreferrer">Rust By Example — Closures</a></li>
<li><a href="https://doc.rust-lang.org/std/ops/trait.Fn.html" target="_blank" rel="noopener noreferrer">Fn, FnMut, and FnOnce — Official Docs</a></li>
<li><a href="https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/" target="_blank" rel="noopener noreferrer">Programming Rust — Jim Blandy & Jason Orendorff</a></li>
<li><a href="https://rust-lang.github.io/api-guidelines/type-safety.html" target="_blank" rel="noopener noreferrer">Rust Design Patterns — Closures</a></li>
</ul>