100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Rust

Closures in Rust

Understand Rust closures, their capture modes, and the Fn, FnMut, and FnOnce traits that govern how they use captured variables.

Functions & ClosuresIntermediate9 min readJul 8, 2026
Analogies

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

rust
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

rust
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

rust
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

Was this page helpful?

Topics covered

#Rust#RustProgrammingStudyNotes#Programming#ClosuresInRust#Closures#Syntax#Explanation#Example#Functions#StudyNotes#SkillVeris