Programación funcional en Rust: técnicas avanzadas y modismos

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: nivel avanzado

\n\n

Rust es un lenguaje multiparadigma que combina de manera orgánica estilos imperativos, orientados a objetos y funcionales. A nivel avanzado, la programación funcional en Rust permite escribir código más seguro, expresivo y conciso. En este artículo, analizaremos conceptos clave: clausuras con captura del entorno, iteradores avanzados, functores y mónadas usando Option y Result, así como currificación y composición de funciones.

\n\n

1. Clausuras: propiedad, préstamo y mutabilidad

\n\n

Las clausuras en Rust no son solo funciones anónimas. Pueden capturar variables del ámbito circundante de tres maneras: por referencia (&T), por referencia mutable (&mut T) y por valor (T). El compilador selecciona automáticamente el trait menos restrictivo: Fn, FnMut o FnOnce.

\n\n

Veamos un ejemplo con captura por valor y uso de move:

\n\n
fn main() {\n    let data = vec![1, 2, 3];\n    \n    // Captura por valor (move) — la propiedad se transfiere a la clausura\n    let closure = move || {\n        println!("{:?}", data);\n        // data ya no está disponible en la función principal\n    };\n    \n    closure();\n    // println!("{:?}", data); // Error: data ha sido movida\n}\n
\n\n

Técnica avanzada: uso de clausuras para crear fábricas de funciones:

\n\n
fn make_multiplier(factor: i32) -> impl Fn(i32) -> i32 {\n    move |x| x * factor\n}\n\nfn main() {\n    let double = make_multiplier(2);\n    let triple = make_multiplier(3);\n    \n    println!("{}", double(5));  // 10\n    println!("{}", triple(5));  // 15\n}\n
\n\n

Aquí, impl Fn(i32) -> i32 es el tipo de retorno de la clausura. Rust genera automáticamente un tipo anónimo que implementa el trait Fn.

\n\n

2. Iteradores avanzados: cadenas, adaptadores y evaluación perezosa

\n\n

Los iteradores en Rust son una herramienta poderosa del estilo funcional. Son perezosos: los cálculos solo ocurren al llamar a un método terminal (collect, for_each, fold, etc.).

\n\n

Veamos un pipeline complejo de procesamiento de datos:

\n\n
fn process_data(data: Vec<i32>) -> Vec<i32> {\n    data.iter()\n        .filter(|&x| x > 0)                     // Dejamos los positivos\n        .map(|x| x * 2)                          // Duplicamos\n        .enumerate()                             // Agregamos índices\n        .filter(|(i, _)| i % 2 == 0)             // Índices pares\n        .map(|(_, x)| x)                         // Extraemos el valor\n        .collect()                               // Método terminal\n}\n
\n\n

Técnica avanzada: uso de flat_map para trabajar con estructuras anidadas y fold para acumulación:

\n\n
fn main() {\n    let nested = vec![vec![1, 2], vec![3, 4, 5], vec![6]];\n    \n    let flattened: Vec<i32> = nested.iter()\n        .flat_map(|v| v.iter())\n        .copied()\n        .collect();\n    \n    println!("{:?}", flattened); // [1, 2, 3, 4, 5, 6]\n    \n    // fold — análogo funcional de reduce\n    let sum = flattened.iter()\n        .fold(0, |acc, x| acc + x);\n    \n    println!("Suma: {}", sum); // 21\n}\n
\n\n

Es importante recordar: las cadenas de iteradores no crean colecciones intermedias a menos que se llame a collect. Esto ahorra memoria y mejora el rendimiento.

\n\n

3. Mónadas Option y Result: manejo funcional de errores

\n\n

En programación funcional, Option y Result son mónadas. Permiten encadenar el procesamiento de valores opcionales y errores sin match o if let anidados.

\n\n

Veamos un escenario típico con verificaciones anidadas:

\n\n


                
                

Blogs

Book Recommendations