Rust Funções Intermediário
Closures
Closures são funções anônimas que capturam variáveis do ambiente onde são definidas. Diferente de funções normais, elas podem acessar variáveis locais sem recebê-las como parâmetro. Em Rust, closures implementam uma das três traits: Fn, FnMut ou FnOnce, dependendo de como capturam e usam as variáveis.
A captura pode ser por empréstimo imutável (Fn), empréstimo mutável (FnMut) ou por movimento (FnOnce). O compilador infere automaticamente qual trait se aplica, mas você pode forçar o movimento com a palavra-chave move. Closures são amplamente usadas como argumentos para funções como map, filter e fold.
Entender as diferenças entre Fn, FnMut e FnOnce é essencial para escrever código genérico que aceita closures. A escolha da trait afeta como a closure pode ser chamada e quantas vezes.
Pontos-chave
- Closures capturam variáveis do ambiente, funções não.
Fnempresta imutavelmente,FnMutempresta mutavelmente,FnOnceconsome.moveforça a captura por valor, útil para threads e retorno de closures.- Closures podem ser passadas como parâmetros usando generics ou trait objects (
impl FnouBox<dyn Fn>). - O compilador infere a trait automaticamente, mas você pode explicitá-la.
fn aplicar<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
f(x)
}
fn main() {
// Closure que captura por empréstimo imutável (Fn)
let fator = 3;
let multiplicar = |x| x * fator;
println!("3 * 5 = {}", multiplicar(5));
// Closure que captura por empréstimo mutável (FnMut)
let mut contador = 0;
let mut incrementar = || {
contador += 1;
contador
};
println!("Contador: {}", incrementar());
println!("Contador: {}", incrementar());
// Closure que consome a variável (FnOnce) com move
let texto = String::from("Olá");
let consumir = move || println!("Texto: {}", texto);
consumir();
// texto não é mais acessível aqui
// Passando closure como parâmetro
let resultado = aplicar(|x| x + 10, 7);
println!("Resultado: {}", resultado);
}