Closure Syntax
A closure is an anonymous function expression written with vertical pipes (|params| body) that can be stored in a variable, passed as an argument, or returned from a function while capturing variables from its enclosing scope.
Anatomy of a Closure Expression
|x: i32, y: i32| -> i32 { x + y }
^^^^^^^^^^^^^^ ^^^ ^^^^^
parameters return body
type
Unlike fn items, type annotations on closure parameters, the return type arrow (-> Type), and curly braces ({}) around a single-expression body are all optional when the compiler can infer them from context:
| Form | Syntax | Notes |
|---|---|---|
| Fully annotated | |x: i32| -> i32 { x + 1 } |
Explicit parameter type, return type, and block |
| Inferred types with block | |x| { x + 1 } |
Braces kept; parameter and return types inferred |
| Single-expression body | |x| x + 1 |
Braces omitted when the body is a single expression |
| Zero parameters | || 42 |
Empty pipes || take no arguments |
| Ignored parameter | |_| println!("called") |
Accepts one argument and discards it |
Note that if you specify an explicit return type (-> T), the closure body must be wrapped in curly braces (|x| -> i32 { x + 1 }).
fn main() {
let add_explicit = |a: i32, b: i32| -> i32 { a + b };
let add_concise = |a, b| a + b;
let greet = || "Hello, Rust!";
println!("Explicit: {}", add_explicit(10, 20));
println!("Concise: {}", add_concise(5, 7));
println!("Greet: {}", greet());
}
Explicit: 30
Concise: 12
Greet: Hello, Rust!
Multi-Statement Closure Bodies
When a closure performs multiple statements before returning a value, wrap the body in { ... } just like a regular function block:
fn main() {
let format_tag = |raw: &str| {
let trimmed = raw.trim();
let lower = trimmed.to_lowercase();
format!("#{lower}")
};
println!("{}", format_tag(" Rust2024 "));
}
#rust2024
Destructuring Patterns in Closure Parameters
Closure parameter lists support irrefutable patterns, allowing you to destructure tuples, structs, or references directly in the |...| header:
struct Point {
x: i32,
y: i32,
}
fn main() {
let manhattan = |Point { x, y }: &Point| x.abs() + y.abs();
let sum_pair = |(a, b): (i32, i32)| a + b;
let p = Point { x: -4, y: 9 };
println!("Manhattan distance: {}", manhattan(&p));
println!("Pair sum: {}", sum_pair((15, 25)));
}
Manhattan distance: 13
Pair sum: 40