¡Bienvenidos de nuevo a Rustaceo.es! En nuestra serie sobre Rust y Pokémon, hoy profundizaremos en closures, una característica poderosa en Rust que nos permite definir funciones anónimas flexibles y eficientes. Exploraremos cómo funcionan, cómo capturan valores y cómo pueden mejorar nuestro código mediante ejemplos del mundo Pokémon. ¡Acompáñame en esta aventura!
🔧 ¿Qué son las closures? #
Las closures en Rust son funciones anónimas que pueden capturar variables del entorno en el que se definen. Son especialmente útiles para operaciones funcionales como filtrado, mapeo y procesamiento de datos.
⚒ Sintaxis de una closure #
let suma = |x, y| x + y;
println!("El resultado es: {}", suma(5, 3)); // Imprime 8
- Se usa
|
para definir los parámetros. - No es necesario especificar los tipos si pueden inferirse.
- El cuerpo puede ser una única expresión o un bloque de código.
Closures con bloques #
Podemos definir closures con más lógica dentro de un bloque:
let multiplicar = |x, y| {
let resultado = x * y;
println!("Multiplicando {} * {}", x, y);
resultado
};
println!("Resultado: {}", multiplicar(4, 6));
📈 Captura de variables en closures #
Las closures pueden capturar variables del entorno de tres maneras:
- Por referencia (
&T
) - Por mutabilidad (
&mut T
) - Por valor (
T
)
Ejemplo:
let mut contador = 0;
let mut incrementar = || {
contador += 1;
println!("Contador: {}", contador);
};
incrementar(); // Contador: 1
incrementar(); // Contador: 2
En este caso, la closure captura contador
por mutabilidad (&mut T
).
Captura por valor #
Si queremos que una closure tome posesión de una variable, podemos usar move
:
let mensaje = String::from("¡Hola, Rust!");
let imprimir = move || println!("{}", mensaje);
imprimir();
// `mensaje` ya no es accesible aquí
📁 Closures en iteradores y funciones funcionales #
Las closures son ideales para trabajar con iteradores y programación funcional.
Uso con map()
#
let elemento_niveles = vec![5, 12, 22, 30];
let duplicados: Vec<_> = elemento_niveles.iter().map(|x| x * 2).collect();
println!("Niveles duplicados: {:?}", duplicados); // [10, 24, 44, 60]
Uso con filter()
#
let niveles_altos: Vec<_> = elemento_niveles.into_iter().filter(|&x| x >= 20).collect();
println!("Pokémon con nivel alto: {:?}", niveles_altos); // [22, 30]
🎯 Tipos de closures en Rust #
Rust clasifica las closures en tres tipos según cómo capturan valores:
Fn
: Captura por referencia.FnMut
: Captura por mutabilidad.FnOnce
: Captura por valor y se consume tras su ejecución.
Ejemplo de FnOnce
:
fn ejecutar<F: FnOnce()>(func: F) {
func();
}
let mensaje = String::from("Ejecutando una closure");
ejecutar(move || println!("{}", mensaje));
Aquí, la closure se consume al ejecutarse porque toma la propiedad de mensaje
.
📊 Conclusión #
Las closures son una herramienta poderosa en Rust para escribir código más expresivo y modular. Combinadas con iteradores y programación funcional, hacen que el código sea más limpio y seguro.
🔮 Próximo paso: ¡Experimenta con closures en tus proyectos y optimiza tu código!
¡Hasta la próxima, Rustaceos!