Programação Funcional em Rust: de A a Z

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Programação Funcional em Rust: de A a Z



A linguagem Rust, conhecida por sua segurança de memória e alto desempenho, também oferece ferramentas poderosas para programação funcional. Diferente de linguagens puramente funcionais (Haskell), Rust permite combinar flexivelmente estilos imperativo e funcional. Neste artigo, exploraremos os conceitos-chave da programação funcional em Rust: desde closures básicas até padrões mônadas avançados. O material será útil tanto para iniciantes quanto para desenvolvedores experientes que desejam escrever código mais conciso e confiável.



1. Fundamentos: Imutabilidade e Variáveis



A programação funcional começa com a imutabilidade. Em Rust, as variáveis são imutáveis por padrão. Esta é uma diferença fundamental em relação a muitas linguagens.



// Variável imutável (padrão)let x = 10;// x = 20; // Erro de compilação!

// Variável mutável (explícita)let mut y = 5;y = 15; // Funciona


O uso de let sem mut garante que o valor não mudará após a inicialização. Isso reduz o número de efeitos colaterais e torna o código mais previsível. No estilo funcional, recomenda-se dar preferência a variáveis imutáveis, criando novos valores em vez de modificar os antigos.



2. Closures — Funções Anônimas



Closures são funções anônimas que podem capturar variáveis de seu ambiente. Em Rust, elas são implementadas através das traits Fn, FnMut e FnOnce.



2.1. Sintaxe e Captura de Variáveis



// Closure simpleslet add_one = |x: i32| -> i32 { x + 1 };println!("{}", add_one(5)); // 6

// Captura de variável do ambientelet base = 10;let add_base = |x| x + base; // base é capturado por referência (&)println!("{}", add_base(20)); // 30

// Captura com mutação (FnMut)let mut counter = 0;let mut increment = || { counter += 1; };increment();increment();println!("{}", counter); // 2

// Captura com consumo (FnOnce)let name = String::from("Rust");let consume = || { drop(name); };consume();// println!("{}", name); // Erro: name foi movido


2.2. Closures como Argumentos de Funções



Closures são frequentemente passadas para funções de ordem superior, como map, filter e fold.



let numbers = vec![1, 2, 3, 4, 5];

// Usando closure com filterlet evens: Vec<i32> = numbers .into_iter() .filter(|&x| x % 2 == 0) .collect();

println!("{:?}", evens); // [2, 4]


3. Iteradores e Cadeias de Transformações



Iteradores são o coração da programação funcional em Rust. Eles são preguiçosos (os cálculos ocorrem apenas ao chamar collect() ou for) e permitem construir cadeias de transformações.



3.1. Adaptadores Básicos de Iteradores



let data = vec![1, 2, 3, 4, 5, 6];

// Cadeia: filter -> map -> take -> collectlet result: Vec<i32> = data .iter() .filter(|&x| x % 2 == 0) // mantém pares .map(|x| x * 2) // dobra .take(2) // pega os dois primeiros .collect();

println!("{:?}", result); // [4, 8]


3.2. Dobra (fold) e Redução



fold é o análogo de reduce em outras linguagens. Ele acumula um resultado, percorrendo todos os elementos.



let numbers = [1, 2, 3, 4, 5];

// Soma de todos os númeroslet sum = numbers.iter().fold(0, |acc, &x| acc + x);println!("Sum: {}", sum); // 15

// Fatoriallet factorial = (1..=5).fold(1, |acc, x| acc * x);println!("5! = {}", factorial); // 120


3.3. Iteradores Preguiçosos Infinitos



// Iterador infinito, pegando os primeiros 10let first_ten: Vec<i32> = (0..)    .filter(|x| x % 2 == 0)    .map(|x| x * x)                

Blogs

Book Recommendations