Welcome back to CodeYourCraft! Today, we're diving into one of Rust's powerful features: Closures as Parameters. This lesson is perfect for beginners and intermediate learners alike. Let's get started!
In Rust, a closure is an anonymous function that can capture and store references to any variables from the outer scope. Closures are syntactically similar to Lambdas, but they can also be assigned to variables and passed as arguments to other functions.
let numbers = vec![1, 2, 3];
let double = |x: i32| -> i32 { x * 2 };
let doubled_numbers = numbers.iter().map(double);In the example above, we've defined a closure double that takes an i32 and returns another i32 by multiplying the input by 2. We then use this closure to double each number in the numbers vector.
Now, let's take it a step further and make our closures reusable by passing them as parameters to other functions.
fn apply_operation<T, F>(values: Vec<T>, operation: F) -> Vec<T>
where
F: FnMut(T) -> T,
{
let mut result = vec![];
for value in values {
let new_value = operation(value);
result.push(new_value);
}
result
}In the code above, we've defined a generic function called apply_operation that takes a vector of values and a closure as a parameter. The closure is expected to be a mutable function that takes a value of the same type as the vector's elements and returns a new value of the same type.
Now, we can use this function to apply different operations to our values by passing different closures as parameters.
fn main() {
let numbers = vec![1, 2, 3];
let doubled_numbers = apply_operation(numbers, |x: i32| -> i32 { x * 2 });
println!("{:?}", doubled_numbers); // prints [2, 4, 6]
let strings = vec!["hello", "world", "rust"];
let capitalized_strings = apply_operation(strings, |s: &str| -> String { s.to_uppercase().into_owned() });
println!("{:?}", capitalized_strings); // prints ["HELLO", "WORLD", "RUST"]
}In the example above, we've used the apply_operation function to double the numbers and capitalize the strings by passing different closures as parameters.
What does the `FnMut` trait represent in Rust?
In this lesson, we've learned about closures and how to pass them as parameters to other functions in Rust. This powerful feature allows us to write reusable and flexible code that can handle a variety of different operations.
As always, remember to keep practicing and don't be afraid to ask questions. Happy coding! 🚀