๐Ÿฆ€ Functional Rust
๐ŸŽฌ Closures in Rust Fn/FnMut/FnOnce, capturing environment, move closures, higher-order functions.
๐Ÿ“ Text version (for readers / accessibility)

โ€ข Closures capture variables from their environment โ€” by reference, mutable reference, or by value (move)

โ€ข Three traits: Fn (shared borrow), FnMut (mutable borrow), FnOnce (takes ownership)

โ€ข Higher-order functions like .map(), .filter(), .fold() accept closures as arguments

โ€ข move closures take ownership of captured variables โ€” essential for threading

โ€ข Closures enable functional patterns: partial application, composition, and strategy

502: Fn, FnMut, FnOnce Hierarchy

Difficulty: 3 Level: Intermediate The three closure traits tell you how many times a closure can be called and what it does to its captures.

The Problem This Solves

You write a function that accepts a closure and hit: `the trait bound FnMut is not satisfied`, or you try to call a closure twice and get `use of moved value`. The root cause is Rust's three-trait hierarchy for closures โ€” and not understanding it means writing overly restrictive or overly permissive function signatures. If you always write `F: Fn(...)`, you reject valid closures that mutate state (counters, accumulators). If you write `F: FnOnce(...)`, you allow callers to pass a one-shot closure into a loop. Getting the bounds right matters for correctness, usability, and compiler error quality. Without this understanding, you'll either make every function too strict (rejecting useful closures) or introduce subtle bugs by calling a closure that should only run once multiple times.

The Intuition

Think of the three traits as permission levels: The hierarchy: `Fn โІ FnMut โІ FnOnce`. Every `Fn` is also `FnMut` and `FnOnce`. But not every `FnOnce` is `FnMut`.

How It Works in Rust

// FnOnce: consumes a captured value โ€” can only be called once
fn make_greeting(name: String) -> impl FnOnce() -> String {
 move || format!("Hello, {}!", name)  // name is moved OUT on call
}
let greet = make_greeting("Alice".to_string());
println!("{}", greet());  // โœ“ first call
// println!("{}", greet()); // โœ— ERROR: value used after move

// FnMut: mutates captures โ€” can be called many times
fn make_counter() -> impl FnMut() -> i32 {
 let mut count = 0;
 move || { count += 1; count }   // mutates captured count
}
let mut counter = make_counter();
println!("{}", counter()); // 1
println!("{}", counter()); // 2

// Fn: read-only captures โ€” freely shareable
fn make_multiplier(factor: i32) -> impl Fn(i32) -> i32 {
 move |x| x * factor    // only reads factor
}
let double = make_multiplier(2);
println!("{}", double(5)); // 10
println!("{}", double(5)); // 10 โ€” still works, nothing consumed

// Function signature best practice: use the least restrictive bound
fn call_once<F: FnOnce() -> String>(f: F) -> String { f() }
fn call_many<F: FnMut() -> i32>(mut f: F) -> Vec<i32> { vec![f(), f(), f()] }
fn apply_pure<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 { f(f(x)) }  // calls twice

What This Unlocks

Key Differences

ConceptOCamlRust
Single-call function`unit -> 'a` (no enforcement)`FnOnce` โ€” compiler enforced
Stateful closure`unit -> 'a` with `ref` inside`FnMut` โ€” requires `&mut self` on call
Pure closure`'a -> 'b` (no restriction)`Fn` โ€” only reads captures
HierarchyNo subtyping between function types`Fn โІ FnMut โІ FnOnce`
Type constraintStructural typingExplicit trait bounds
//! # 502. Fn, FnMut, FnOnce Hierarchy
//! Demonstrates the three closure trait bounds and their relationships.

/// Accepts any callable โ€” even one-shot closures
/// FnOnce is the most permissive bound (all closures satisfy it)
fn call_once<F: FnOnce() -> String>(f: F) -> String {
    f()
}

/// Accepts callables that can be invoked multiple times with state
fn call_three_times<F: FnMut() -> i32>(mut f: F) -> Vec<i32> {
    vec![f(), f(), f()]
}

/// Accepts only pure, non-mutating callables
/// Can be called from multiple threads safely
fn apply_twice<F: Fn(i32) -> i32>(f: F, x: i32) -> i32 {
    f(f(x))
}

/// Demonstrate FnOnce: consumes a captured value
fn make_greeting(name: String) -> impl FnOnce() -> String {
    move || format!("Hello, {}!", name) // name is consumed on call
}

/// Demonstrate FnMut: maintains counter state
fn make_counter() -> impl FnMut() -> i32 {
    let mut count = 0;
    move || {
        count += 1;
        count
    }
}

/// Demonstrate Fn: pure transformation
fn make_multiplier(factor: i32) -> impl Fn(i32) -> i32 {
    move |x| x * factor
}

/// A generic "call N times" โ€” works with FnMut
fn repeat<F: FnMut() -> T, T>(mut f: F, n: usize) -> Vec<T> {
    (0..n).map(|_| f()).collect()
}

fn main() {
    // FnOnce example
    println!("=== FnOnce ===");
    let greet = make_greeting(String::from("Alice"));
    println!("{}", call_once(greet));
    // greet is consumed โ€” can't use it again

    // FnMut example
    println!("\n=== FnMut ===");
    let counter = make_counter();
    let counts = repeat(counter, 5);
    println!("Counts: {:?}", counts);

    let mut stateful_counter = make_counter();
    let results = call_three_times(&mut stateful_counter);
    println!("call_three_times: {:?}", results);

    // Fn example
    println!("\n=== Fn ===");
    let double = make_multiplier(2);
    println!("apply_twice(double, 3) = {}", apply_twice(&double, 3)); // 12
    println!("apply_twice(double, 5) = {}", apply_twice(&double, 5)); // 20
    // double is still usable because Fn doesn't consume

    // Hierarchy demonstration: Fn satisfies FnMut and FnOnce
    println!("\n=== Hierarchy: Fn satisfies FnMut and FnOnce ===");
    let pure_const = || 42i32;
    // pure_const implements Fn, FnMut, AND FnOnce
    let _ = call_three_times(pure_const);  // FnMut bound โ€” works!
    call_once(|| String::from("done")); // FnOnce bound โ€” works!
    println!("Fn closures satisfy all three trait bounds");
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_fn_once() {
        let s = String::from("test");
        let f = move || s.to_uppercase();
        assert_eq!(call_once(f), "TEST");
    }

    #[test]
    fn test_fn_mut_counter() {
        let mut c = make_counter();
        assert_eq!(c(), 1);
        assert_eq!(c(), 2);
        assert_eq!(c(), 3);
    }

    #[test]
    fn test_fn_pure() {
        let triple = make_multiplier(3);
        assert_eq!(apply_twice(&triple, 2), 18); // triple(triple(2)) = triple(6) = 18
    }

    #[test]
    fn test_repeat() {
        let mut n = 0;
        let results = repeat(|| { n += 1; n }, 4);
        assert_eq!(results, vec![1, 2, 3, 4]);
    }

    #[test]
    fn test_hierarchy() {
        // A pure Fn closure can be used wherever FnMut or FnOnce is expected
        let g = || 42i32;
        assert_eq!(call_three_times(g), vec![42, 42, 42]);
        // Fn satisfies FnOnce too:
        let result = call_once(|| String::from("from Fn"));
        assert_eq!(result, "from Fn");
    }
}
(* OCaml has no enforcement โ€” all functions are just values *)
(* But we can simulate the concepts *)

(* "FnOnce" โ€” consume a resource on first call *)
let make_once_consumer value =
  let used = ref false in
  fun () ->
    if !used then failwith "already consumed!"
    else begin used := true; value end

(* "FnMut" โ€” maintains mutable state across calls *)
let make_counter () =
  let count = ref 0 in
  fun () -> incr count; !count

(* "Fn" โ€” pure, no state *)
let make_adder n = fun x -> x + n

(* Higher-order: call a function multiple times *)
let call_n_times f n =
  for _ = 1 to n do f () done

let () =
  (* Once-consumer *)
  let consume = make_once_consumer "treasure" in
  Printf.printf "First call: %s\n" (consume ());
  (try let _ = consume () in () with Failure msg -> Printf.printf "Error: %s\n" msg);

  (* Counter (FnMut analog) *)
  let counter = make_counter () in
  call_n_times (fun () ->
    Printf.printf "count: %d\n" (counter ())
  ) 3;

  (* Adder (Fn analog) *)
  let add5 = make_adder 5 in
  Printf.printf "add5(3) = %d\n" (add5 3);
  Printf.printf "add5(10) = %d\n" (add5 10)