💻 Exemplos: Capítulo 14: Closures, Captura de Ambiente e Programação Funcional

Especialização em Sistemas com Rust • Demonstrações Práticas Compiláveis


🎯 Objetivo dos Exemplos

Apresentar a sintaxe e a semântica de Closures em Rust, as 3 traits de chamada do compilador (Fn, FnMut e FnOnce), a palavra-chave move para transferir o ownership de variáveis capturadas e a construção de funções de alta ordem personalizadas.


1. Código Fonte Completo (src/main.rs)

//! Closures, Traits de Captura (Fn, FnMut, FnOnce) e Higher-Order Functions

/// Função de Alta Ordem (Higher-Order Function)
/// Recebe uma closure genérica F que implementa o trait Fn(i32) -> i32
fn aplicar_transformacao<F>(valor: i32, transformador: F) -> i32
where
    F: Fn(i32) -> i32,
{
    transformador(valor)
}

/// Recebe uma closure que muta seu próprio ambiente interno (FnMut)
fn executar_acumulador_n_vezes<F>(mut acumulador: F, iteracoes: usize)
where
    F: FnMut(usize),
{
    for i in 1..=iteracoes {
        acumulador(i);
    }
}

/// Recebe uma closure que consome a si mesma (FnOnce)
fn executar_e_destruir<F>(operacao: F)
where
    F: FnOnce() -> String,
{
    let resultado = operacao();
    println!("  Resultado da closure FnOnce: '{}'", resultado);
}

fn main() {
    println!("=== CLOSURES E PROGRAMAÇÃO FUNCIONAL EM RUST ===");

    // 1. Closure básica com inferência de tipos
    let multiplicador_base = 10;
    // Captura 'multiplicador_base' por referência imutável (&) -> Implementa 'Fn'
    let calcular_fator = |x: i32| x * multiplicador_base;

    let res = aplicar_transformacao(5, calcular_fator);
    println!("Resultado da transformação via Fn: {}", res);
    println!("Multiplicador base continua acessível: {}", multiplicador_base);

    // 2. Closure com mutação do ambiente capturado (FnMut)
    let mut total_bytes_processados = 0;
    println!("\nIniciando acumulador mutável com FnMut:");
    
    let mut registrar_bloco = |indice: usize| {
        let bytes_bloco = indice * 64;
        total_bytes_processados += bytes_bloco;
        println!("  Passo {}: +{} bytes adicionados (Total acumulado: {})", indice, bytes_bloco, total_bytes_processados);
    };

    executar_acumulador_n_vezes(&mut registrar_bloco, 3);
    println!("Total consolidado após FnMut: {} bytes", total_bytes_processados);

    // 3. A palavra-chave 'move' (Transferindo Ownership para a Closure)
    let dados_criticos = String::from("CHAVE_CRIPTOGRAFICA_MESTRE");
    
    // 'move' força a transferência do ownership de 'dados_criticos' para dentro da closure
    let closure_proprietaria = move || {
        format!("Cifra processada com base em: [{}]", dados_criticos)
        // 'dados_criticos' é consumido e destruído aqui
    };

    // 'dados_criticos' não pode mais ser lida na main!
    // println!("{}", dados_criticos); // ERRO: value borrowed here after move

    executar_e_destruir(closure_proprietaria);

    // 4. Combinando Closures com Iteradores Nativos
    println!("\nFiltrando e mapeando eventos de telemetria:");
    let leituras = vec![12.5, 45.0, 88.2, 105.4, 23.1, 99.9];
    
    let leituras_anormais: Vec<f64> = leituras
        .into_iter()
        .filter(|&pressao| pressao > 80.0)
        .map(|pressao| (pressao * 1.1).round())
        .collect();

    println!("Leituras anormais corrigidas (+10%): {:?}", leituras_anormais);
}

2. Saída Esperada no Terminal

=== CLOSURES E PROGRAMAÇÃO FUNCIONAL EM RUST ===
Resultado da transformação via Fn: 50
Multiplicador base continua acessível: 10

Iniciando acumulador mutável com FnMut:
  Passo 1: +64 bytes adicionados (Total acumulado: 64)
  Passo 2: +128 bytes adicionados (Total acumulado: 192)
  Passo 3: +192 bytes adicionados (Total acumulado: 384)
Total consolidado após FnMut: 384 bytes
  Resultado da closure FnOnce: 'Cifra processada com base em: [CHAVE_CRIPTOGRAFICA_MESTRE]'

Filtrando e mapeando eventos de telemetria:
Leituras anormais corrigidas (+10%): [97.0, 116.0, 110.0]