liveBook · Manning

Fn

As explained in Learn Rust in a Month of Lunches

Fn is a Rust trait for closures and callable values that can be called repeatedly through shared access without consuming or mutating their captured environment.

`Fn` is a Rust trait for a closure that can be called repeatedly through shared access. A closure that only reads a captured value can use `Fn`: for example, one that prints a `String` without changing it can run twice. section 11.6.3

fn takes_fn<F: Fn()>(f: F) {
    f();
    f();
}

The `Fn()` bound lets `takes_fn` call its argument twice. The empty parentheses mean this closure takes no arguments. section 12.1.1

Choose `Fn` in a function signature when the function needs that repeatable, non-mutating behavior. A closure that changes a captured value uses `FnMut`; one that consumes a captured value may be callable only once and uses `FnOnce`. The compiler determines what a closure can do, but you choose the trait bound when accepting it as an argument. section 11.6.3 section 12.1

The traits fit together: `Fn` also implements `FnMut` and `FnOnce`. So a function accepting `FnOnce` can accept an `Fn` closure, but a function requiring `Fn` cannot accept every `FnMut` or `FnOnce` closure. `Fn` is the most restrictive bound for the caller supplying a closure. section 12.1.2

Two closures, two types

Even two separate closures that both return `9` have different concrete types. To accept both as arguments, give them separate generic parameters, each bounded by `Fn() -> i32`. `Fn` describes what each closure can do; it is not their shared concrete type. section 12.1.3

For a spawned thread, a closure that merely prints an outside `String` would normally borrow it. If that borrow might outlive the current function, the compiler suggests `move` so the closure owns the value. The thread API accepts `FnOnce`; needing `move` here is about ownership, not about printing changing the string. section 11.6.4

How Learn Rust in a Month of Lunches covers it

How deep it goes
Explains capture behavior, generic bounds, trait relationships, and distinct closure types; defers trait objects.
Examples
Uses a String-printing closure called twice, a two-call function, and two identical-looking closures with different types.
What it assumes
Assumes basic Rust closures and borrowing while walking through how generic closure bounds are written.
What you can do after
Build it from scratch: write an Fn-bounded function and distinguish when a closure instead needs FnMut or FnOnce.
How it connects
Connects Fn to FnMut, FnOnce, borrowing, generic trait bounds, and thread closures.

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.