← Back to Rust Course | Chapter 14: Closures, Iterators & Async | Lesson 1 of 6

Closure Traits: Fn, FnMut, FnOnce

There are three flavors of closures depending on whether they just look at, change, or use up the things they grabbed.

Fn: Read-Only Captures

A closure that only reads captured variables implements Fn, and can be called multiple times without any restriction.

Example: Fn: Read-Only Captures

markup
fn main() {
    let greeting = String::from("Hello");
    let greet = || println!("{}, world!", greeting);
    greet();
    greet();
}

FnMut: Mutating Captures

A closure that mutates a captured variable implements FnMut; the variable holding the closure must itself be mut to call it.

Example: FnMut: Mutating Captures

markup
fn main() {
    let mut count = 0;
    let mut increment = || {
        count += 1;
        println!("count is now {}", count);
    };
    increment();
    increment();
}

FnOnce: Consuming Captures

A closure that moves a captured variable out of itself (for example, returning owned data) implements only FnOnce, meaning it can be called at most one time.

Example: FnOnce: Consuming Captures

markup
fn main() {
    let text = String::from("consumed");
    let consume = move || {
        let owned = text;
        println!("Consumed inside closure: {}", owned);
    };
    consume();
}

Forcing Ownership with move

The move keyword forces a closure to take ownership of every variable it captures, rather than borrowing them, which is required when the closure needs to outlive its original scope.

Example: Forcing Ownership with move

markup
fn main() {
    let data = vec![1, 2, 3];
    let owns_data = move || println!("Owned inside closure: {:?}", data);
    owns_data();
}
Common Mistakes
  1. Trying to call an FnOnce closure more than once -- by definition it can only be called a single time.
  2. Requiring Fn in a function signature when the closure passed actually needs to mutate captured state, requiring FnMut instead.
  3. Forgetting the move keyword forces a closure to take ownership of captured variables instead of borrowing them.
Chapter Summary
  • Fn closures can be called repeatedly and only borrow captured variables immutably.
  • FnMut closures can be called repeatedly and may mutate captured variables.
  • FnOnce closures can only be called once, since they consume (move) captured variables.
  • The move keyword forces a closure to take ownership of the variables it captures rather than borrowing them.
🔒

Chapter Quiz — Complete all 6 topics to unlock

0/6 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.