Conquer Collections with Ease: Mastering Iterators and Closures in Rust
Explanation of iterators and closures in Rust, along with code to filter a list of strings:
Iterators:
- Purpose: Iterators provide a way to consume a collection of elements sequentially without needing to access the entire collection at once. This promotes efficient memory usage and lazy evaluation.
- Creation: They are often created using methods like iter() on collections like vectors and slices.
- Methods: Iterators offer various methods for manipulating and consuming elements:
- next(): Returns the next element, or None if iteration is finished.
- filter(): Creates a new iterator that only yields elements matching a predicate.
- map(): Transforms each element using a given closure.
- collect(): Gathers elements into a new collection.
Closures:
- Purpose: Closures are anonymous functions that can capture variables from their surrounding environment. This allows flexible code reuse and concise expression of behavior.
- Syntax: Closures have the form |parameters| expression.
- Captures: They can capture variables using & (borrowing) or move (taking ownership).
Code to remove elements starting with "a":
Rust
fn remove_starting_with_a(list: &mut Vec<String>) {
list.retain(|s| !s.starts_with("a"));
}
fn main() {
let mut list = vec!["apple", "banana", "apricot", "cherry"];
remove_starting_with_a(&mut list);
assert_eq!(list, vec!["banana", "cherry"]);
}
Explanation:
- remove_starting_with_a takes a mutable reference to a Vec<String>.
- retain iterates through elements and keeps those for which the closure returns true.
- The closure |s| !s.starts_with("a") captures s by reference and checks if it doesn't start with "a".
- The resulting iterator is consumed by retain, effectively removing elements that start with "a".