Introduction
A closure is an anonymous function-like construct that can capture variables from the scope in which it is defined. Closures are widely used in Rust for passing behavior into functions, especially with iterator adapters. Unlike regular functions, closures can access variables from their enclosing environment, and Rust's type system tracks exactly how each closure captures its environment.
Cricket analogy: A closure is like a fielding drill a coach designs on the spot that remembers the specific pitch conditions of that day's net session, and it gets handed to any bowler to run, much as closures get passed into iterator methods.
Syntax
let add_one = |x| x + 1;
let add = |x: i32, y: i32| -> i32 { x + y };
let greet = move || println!("hello");Explanation
Closures are written between pipes (| |) for parameters, optionally followed by a body expression or block. Type annotations are usually optional because Rust infers them from usage. Closures capture variables in one of three ways depending on how they use them: by immutable reference (Fn trait), by mutable reference (FnMut trait), or by taking ownership (FnOnce trait). The move keyword forces a closure to take ownership of the variables it captures, which is required when the closure needs to outlive the scope it was created in, such as when passed to another thread.
Cricket analogy: Writing |ball| ball.speed between pipes is like a scorer's shorthand that reads a delivery's speed without touching the stumps (Fn, immutable borrow); a shorthand that updates the scoreboard mutably borrows it (FnMut), and one that consumes the match ball entirely as a souvenir is like FnOnce taking ownership, needed when handed to a touring team (another thread) via move.
Example
fn main() {
let factor = 3;
let multiply = |n: i32| n * factor; // borrows factor
println!("6 * 3 = {}", multiply(6));
let mut count = 0;
let mut increment = || {
count += 1; // mutably borrows count
println!("count = {}", count);
};
increment();
increment();
let data = vec![1, 2, 3];
let consume = move || println!("owned data: {:?}", data); // takes ownership
consume();
}Output
6 * 3 = 18
count = 1
count = 2
owned data: [1, 2, 3]Key Takeaways
- Closures are defined with pipe syntax, e.g. |x, y| x + y.
- Closures can capture variables by reference, mutable reference, or by value.
- The move keyword forces the closure to take ownership of captured variables.
- Fn closures borrow, FnMut closures mutably borrow, FnOnce closures consume captured values.
- Closures are commonly passed to functions and iterator adapters as arguments.
Practice what you learned
1. Which syntax correctly defines a closure that takes an i32 and returns it incremented by one?
2. What does the move keyword do when applied to a closure?
3. Which trait describes a closure that mutably borrows variables from its environment?
4. A closure that consumes and takes ownership of a captured value, and therefore can only be called once, implements which trait?
5. In the example `let mut count = 0; let mut increment = || { count += 1; };`, how does the closure capture count?
Was this page helpful?
You May Also Like
Functions in Rust
Learn how to declare, call, and return values from functions using Rust's fn syntax and expression-based return rules.
Higher-Order Functions and Iterators in Rust
Explore functions that take or return closures, the Iterator trait, and lazy adapters like map, filter, and fold.
Ownership in Rust
Rust's core memory-safety system where every value has exactly one owner and is dropped when that owner goes out of scope.
Borrowing and References in Rust
How Rust lets code access data without taking ownership, using immutable and mutable references checked by the borrow checker.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics