Programación funcional en Rust: de la A a la Z

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Programación funcional en Rust: de la A a la Z



El lenguaje Rust, conocido por su gestión segura de la memoria y alto rendimiento, también ofrece potentes herramientas para la programación funcional. A diferencia de los lenguajes puramente funcionales (Haskell), Rust permite combinar de manera flexible estilos imperativos y funcionales. En este artículo, analizaremos los conceptos clave de la programación funcional en Rust: desde closures básicos hasta patrones monádicos avanzados. El material será útil tanto para principiantes como para desarrolladores experimentados que deseen escribir código más conciso y confiable.



1. Fundamentos: Inmutabilidad y variables



La programación funcional comienza con la inmutabilidad. En Rust, las variables son inmutables por defecto. Esta es una diferencia clave con respecto a muchos lenguajes.



// Variable inmutable (por defecto)let x = 10;// x = 20; // ¡Error de compilación!

// Variable mutable (explícitamente)let mut y = 5;y = 15; // Funciona


El uso de let sin mut garantiza que el valor no cambiará después de la inicialización. Esto reduce la cantidad de efectos secundarios y hace que el código sea más predecible. En el estilo funcional, se recomienda dar preferencia a las variables inmutables, creando nuevos valores en lugar de modificar los antiguos.



2. Closures — funciones anónimas



Los closures son funciones anónimas que pueden capturar variables de su entorno. En Rust, se implementan a través de los traits Fn, FnMut y FnOnce.



2.1. Sintaxis y captura de variables



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

// Captura de variable del entornolet base = 10;let add_base = |x| x + base; // base se captura por referencia (&)println!("{}", add_base(20)); // 30

// Captura con mutación (FnMut)let mut counter = 0;let mut increment = || { counter += 1; };increment();increment();println!("{}", counter); // 2

// Captura con consumo (FnOnce)let name = String::from("Rust");let consume = || { drop(name); };consume();// println!("{}", name); // Error: name ha sido movido


2.2. Closures como argumentos de funciones



Los closures a menudo se pasan a funciones de orden superior, como map, filter y fold.



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

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

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


3. Iteradores y cadenas de transformaciones



Los iteradores son el corazón de la programación funcional en Rust. Son perezosos (los cálculos ocurren solo al llamar a collect() o for) y permiten construir cadenas de transformaciones.



3.1. Adaptadores básicos de iteradores



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

// Cadena: filter -> map -> take -> collectlet result: Vec<i32> = data .iter() .filter(|&x| x % 2 == 0) // dejamos los pares .map(|x| x * 2) // duplicamos .take(2) // tomamos los dos primeros .collect();

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


3.2. Pliegue (fold) y reducción



fold es el análogo de reduce en otros lenguajes. Acumula un resultado recorriendo todos los elementos.



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

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

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


3.3. Iteradores infinitos perezosos



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

Blogs

Book Recommendations