liveBook · Manning

Closure

As explained in Learn Rust in a Month of Lunches

A closure is an anonymous Rust function-like value that can capture variables from its surrounding environment and be passed as an argument.

A closure is a short, function-like value written with `| |` instead of a function’s `( )`. It often has no name: you can write one directly where a method needs it. You can also bind one to a variable and call it later. Inputs go between the bars, as in `|x: i32|`; a longer body goes inside `{ }`. section 8.3

fn main() {
    let number_one = 6;
    let number_two = 10;
    let my_closure = || println!("{}", number_one + number_two);
    my_closure();
}

The closure prints the sum of two nearby variables, even though its `||` declares no inputs. This is called capturing variables from its environment. section 8.3

Closures are especially handy in iterator methods. In `.map(|x| x + 1)`, the method supplies each item as `x`, and the closure says what to do with it. `.for_each()` likewise runs a closure for each item without making a new iterator. If a method supplies an argument you do not need, write `|_|`, not `||`: the closure must still accept that argument. section 8.2 section 8.3.3

How a closure uses a captured variable matters. `Fn` uses a regular reference; `FnMut` can change the captured value through a mutable reference; `FnOnce` takes a value and may therefore be callable only once. When a function accepts a closure, its signature specifies the needed trait and the closure’s inputs and output. For example, `F: FnMut(Self::Item) -> bool` requires a closure that accepts an iterator item and returns a Boolean. section 11.6.3 section 12.1

Why two identical-looking closures can fail

Suppose a function declares both of its closure arguments as the same generic type `F`. Passing it two separately written `|| 9` closures fails: each closure has its own type, even though both return an `i32`. Give the arguments separate generic types, such as `F` and `G`, each with an `Fn() -> i32` bound. section 12.1.3

A function can return a closure too, using a return type such as `impl FnMut(i32) -> i32`. Start with the simple question—what inputs does the closure take, and what does it return?—then choose the closure trait that fits how it uses captured values. section 12.2.2 section 12.6

How Learn Rust in a Month of Lunches covers it

How deep it goes
Works through syntax, capture, the three closure traits, signatures, unique types, and returned closures; defers detailed closure-type internals.
Examples
Uses captured numbers, iterator transformations, compiler errors for missing arguments and distinct closure types, and functions that call closures.
What it assumes
Builds closure syntax from regular functions and uses familiarity with variables, references, iterators, and function signatures for later examples.
What you can do after
Apply closures in iterator methods and function arguments, selecting `Fn`, `FnMut`, or `FnOnce` to fit captured-value use.
How it connects
Connects closures to iterators, method chaining, generic type bounds, ownership, and `impl Trait`.

Also explained in

Compare how 20 books explain closure →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Learn Rust in a Month of Lunches. The section links point to the parts of the book it draws on.