Iterators & Closures: The "Functional Powerhouse"
If you’re coming from modern JavaScript, you’re already used to Functional Programming. You use .map(), .filter(), and .reduce() every day.
In Rust, Iterators and Closures are the Functional Powerhouse of the language. They give you the same declarative “what” syntax of JS with the “how” performance of manual assembly.
🏗️ The 3-Step Narrative
1. The Closure (The “Lambda” Contract)
In JS, you write (x) => x + 1. In Rust, you use the |x| x + 1 syntax.
Think of a closure as an Anonymous Contract that captures its environment (the variables around it) and processes them on the fly.
let x = 4;let equal_to_x = |z| z == x; // 🪄 Capture x from the environmentNOTE: Move Closures
If you need the closure to take Ownership of the data it captures, you use the
movekeyword:move |z| z == x.
2. The Iterator (The “Lazy” Contract)
In JS, .map() creates a new array immediately. In Rust, an Iterator is Lazy. It signs a contract that says: “I will transform this data, but only when you actually ask for the results.”
let v1 = vec![1, 2, 3];let v1_iter = v1.iter(); // ⏳ Nothing happens yet!
for val in v1_iter { println!("Got: {val}"); // 🪄 Execution happens here}3. The Functional Chain
You can chain these together to build complex data processing pipelines that look exactly like your favorite JS code.
let v: Vec<i32> = vec![1, 2, 3];
let result: Vec<i32> = v.iter() .map(|x| x + 1) // 🗺️ Transformation .filter(|x| *x > 2) // 🔍 Filtering .collect(); // 📦 Consuming and turning back into a Vec🔬 From the Official Book
⚡ Zero-Cost Abstractions
Iterators are one of Rust’s most famous “Zero-Cost Abstractions.” The compiler is so smart that it transforms your high-level functional code into the exact same machine code as a manual for loop. You get the beauty of functional syntax without the speed penalty of JS’s garbage-collected objects.
💡 What Iterators and Closures Unlock
- Declarative Logic: Write clean, readable code that explains what your data should look like, not how to loop through it.
- Lazy Evaluation: Process massive amounts of data without ever storing the intermediate steps in memory.
- Zero-Cost Performance: Get the same speed as a manually written assembly loop with the safety of a functional language.
- Fearless Refactoring: Because the traits are so strictly typed, you can chain dozens of operations together and know that every step is memory-safe.