Closures Basics
7 examples - 5 basic, 2 intermediate - for closures and capture.
Prerequisites
Basic Examples
1. Closure Syntax
fn main() {
let add = |a: i32, b: i32| a + b;
println!("{}", add(2, 3));
}- Parameters optional types when inferrable
- Body can be expression or block
2. Capture by Reference
fn main() {
let factor = 2;
let scale = |x| x * factor;
println!("{}", scale(5));
}- Closure borrows
factorimmutably - Inferred
Fntrait
3. move Closure
use std::thread;
fn main() {
let msg = String::from("hi");
thread::spawn(move || println!("{msg}"));
}moveforces capture by value into closure
4. With Iterator
fn main() {
let v: Vec<_> = (0..5).map(|n| n * 2).collect();
println!("{:?}", v);
}5. Type Inference
fn apply(f: impl Fn(i32) -> i32, x: i32) -> i32 { f(x) }Related: Fn, FnMut & FnOnce
Intermediate Examples
6. Mutable Capture
fn main() {
let mut count = 0;
let mut inc = || { count += 1; };
inc();
println!("{count}");
}7. Returning Closures Preview
fn make_adder(n: i32) -> impl Fn(i32) -> i32 {
move |x| x + n
}Related: Closures Best Practices
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.