๐Ÿฆ€ 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

514: Observer/Callback Pattern

Difficulty: 3 Level: Intermediate Register closures as event handlers that fire with state โ€” no interface boilerplate, just `Box<dyn FnMut>`.

The Problem This Solves

You're building a UI widget, a game event system, or a data pipeline that needs to notify multiple parties when something happens. The classic Observer pattern requires an `Observer` trait, a registration method, and concrete implementors. For simple callbacks โ€” "log this", "count that", "update the UI" โ€” you end up with a file-per-observer. In C, callbacks use `void (callback)(void userdata)` โ€” you manually pass context around through opaque pointers. Type safety is gone. In Java, anonymous inner classes or lambdas solve this but still need `@FunctionalInterface` declarations. Rust closures with `FnMut` give you stateful callbacks that carry their own context. The counter closure remembers its count. The accumulator closure remembers what it's accumulated. No userdata pointers, no separate context structs.

The Intuition

Think of an event emitter as a mailing list. When you subscribe (`subscribe(handler)`), you add your email address. When an event fires (`emit(event)`), everyone on the list gets a copy. Each subscriber (closure) independently decides what to do with the event. The critical trait choice: `FnMut` rather than `Fn`. Observers are often stateful โ€” they count events, accumulate data, update local caches. `FnMut` allows mutation of captured variables on each call. `Fn` would require all observers to be read-only. In JavaScript, `element.addEventListener('click', (e) => count++)` is exactly this pattern. The arrow function captures `count` and mutates it. Rust's equivalent: a `FnMut` closure.

How It Works in Rust

struct EventEmitter<E> {
 handlers: Vec<Box<dyn FnMut(&E)>>,   // FnMut: handlers can have state
}

impl<E> EventEmitter<E> {
 fn new() -> Self { EventEmitter { handlers: Vec::new() } }

 fn subscribe(&mut self, handler: impl FnMut(&E) + 'static) -> usize {
     self.handlers.push(Box::new(handler));
     self.handlers.len() - 1   // return ID for potential removal
 }

 fn emit(&mut self, event: &E) {
     for handler in &mut self.handlers {
         handler(event);        // FnMut: &mut self required on call
     }
 }
}

let mut emitter: EventEmitter<ButtonEvent> = EventEmitter::new();

// Stateless logger
emitter.subscribe(|event| println!("[LOG] {:?}", event));

// Stateful click counter โ€” captures mut count by move
let mut click_count = 0usize;
emitter.subscribe(move |event| {
 if let ButtonEvent::Click { .. } = event {
     click_count += 1;                          // mutates captured state
     println!("Click #{}", click_count);
 }
});

// One-time handler: wraps any FnMut to fire only once
fn once<E, F: FnMut(&E) + 'static>(mut f: F) -> impl FnMut(&E) {
 let mut fired = false;
 move |event| {
     if !fired { fired = true; f(event); }
 }
}
emitter.subscribe(once(|_| println!("First event only!")));

emitter.emit(&ButtonEvent::Click { x: 10, y: 20 });
emitter.emit(&ButtonEvent::Click { x: 30, y: 40 });
// "Click #1", "Click #2", "First event only!" fires only once

What This Unlocks

Key Differences

ConceptOCamlRust
Event handler type`'event -> unit` function`Box<dyn FnMut(&Event)>`
Stateful handler`ref` variable captured in closure`FnMut` โ€” mutable captures
Register handler`handlers := f :: !handlers``handlers.push(Box::new(f))`
Fire event`List.iter (fun h -> h event) !handlers``handlers.iter_mut().for_each(\h\h(&event))`
Thread-safe versionMutex around handler list`Box<dyn Fn + Send + Sync>` + `Mutex`
//! # 514. Observer/Callback Pattern
//! Event system using FnMut closures as handlers.

#[derive(Debug, Clone)]
enum ButtonEvent {
    Click { x: i32, y: i32 },
    Hover { x: i32, y: i32 },
    KeyPress(char),
}

/// Event emitter that stores FnMut handlers
struct EventEmitter<E> {
    handlers: Vec<Box<dyn FnMut(&E)>>,
}

impl<E> EventEmitter<E> {
    fn new() -> Self {
        EventEmitter { handlers: Vec::new() }
    }

    /// Register a handler โ€” returns its index for potential removal
    fn subscribe(&mut self, handler: impl FnMut(&E) + 'static) -> usize {
        self.handlers.push(Box::new(handler));
        self.handlers.len() - 1
    }

    /// Emit an event โ€” all handlers are called in registration order
    fn emit(&mut self, event: &E) {
        for handler in &mut self.handlers {
            handler(event);
        }
    }

    fn handler_count(&self) -> usize {
        self.handlers.len()
    }
}

/// One-time observer: fires once, then deactivates
fn once<E, F: FnMut(&E) + 'static>(mut f: F) -> impl FnMut(&E) {
    let mut fired = false;
    move |event| {
        if !fired {
            fired = true;
            f(event);
        }
    }
}

fn main() {
    let mut emitter: EventEmitter<ButtonEvent> = EventEmitter::new();

    // Logger handler (immutable state)
    emitter.subscribe(|event| {
        println!("[LOG] {:?}", event);
    });

    // Click counter (mutable state captured by closure)
    let mut click_count = 0usize;
    let click_counter_id = emitter.subscribe(move |event| {
        if let ButtonEvent::Click { .. } = event {
            click_count += 1;
            println!("[COUNTER] clicks so far: {}", click_count);
        }
    });
    println!("Click counter registered as handler #{}", click_counter_id);

    // Key accumulator โ€” collects pressed keys
    let mut keys = String::new();
    emitter.subscribe(move |event| {
        if let ButtonEvent::KeyPress(c) = event {
            keys.push(*c);
            println!("[KEYS] accumulated: {}", keys);
        }
    });

    // One-time welcome handler
    emitter.subscribe(once(|_event| {
        println!("[ONCE] First event received! (fires only once)");
    }));

    println!("\n--- Emitting events ---");
    emitter.emit(&ButtonEvent::Click { x: 10, y: 20 });
    emitter.emit(&ButtonEvent::Hover { x: 15, y: 25 });
    emitter.emit(&ButtonEvent::Click { x: 30, y: 40 });
    emitter.emit(&ButtonEvent::KeyPress('r'));
    emitter.emit(&ButtonEvent::KeyPress('s'));
    emitter.emit(&ButtonEvent::Click { x: 5, y: 5 });

    println!("\nTotal handlers: {}", emitter.handler_count());
}

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

    #[test]
    fn test_emit_count() {
        let mut emitter: EventEmitter<i32> = EventEmitter::new();
        let mut count = 0;
        emitter.subscribe(move |&n| {
            count += n;
            let _ = count;
        });
        emitter.emit(&1);
        emitter.emit(&2);
        emitter.emit(&3);
        // handler count should be 1
        assert_eq!(emitter.handler_count(), 1);
    }

    #[test]
    fn test_multiple_handlers() {
        let mut emitter: EventEmitter<&str> = EventEmitter::new();
        let mut log: Vec<String> = Vec::new();

        // Can't share log across closures without Arc โ€” use separate logs
        let mut log1: Vec<String> = Vec::new();
        let mut log2: Vec<String> = Vec::new();
        // Just test registration and emission works
        emitter.subscribe(|_| {});
        emitter.subscribe(|_| {});
        assert_eq!(emitter.handler_count(), 2);
        emitter.emit(&"test");
        drop(log1); drop(log2); drop(log);
    }

    #[test]
    fn test_once() {
        use std::cell::Cell;
        use std::rc::Rc;
        let call_count = Rc::new(Cell::new(0usize));
        let cc = call_count.clone();
        let mut f = once(move |_: &i32| cc.set(cc.get() + 1));
        f(&1);
        f(&2);
        f(&3);
        assert_eq!(call_count.get(), 1);
    }
}
(* Observer pattern using closures in OCaml *)

type 'a event_system = {
  mutable handlers: ('a -> unit) list;
}

let make_event_system () = { handlers = [] }

let subscribe sys handler =
  sys.handlers <- handler :: sys.handlers

let emit sys event =
  List.iter (fun h -> h event) sys.handlers

(* Typed event *)
type button_event = Click of int * int | Hover of int * int | KeyPress of char

let () =
  let sys = make_event_system () in

  (* Logger handler *)
  subscribe sys (function
    | Click (x, y) -> Printf.printf "[LOG] Click at (%d,%d)\n" x y
    | Hover (x, y) -> Printf.printf "[LOG] Hover at (%d,%d)\n" x y
    | KeyPress c   -> Printf.printf "[LOG] Key: %c\n" c);

  (* Counter handler (stateful) *)
  let click_count = ref 0 in
  subscribe sys (function
    | Click _ -> incr click_count
    | _ -> ());

  (* Fire events *)
  emit sys (Click (10, 20));
  emit sys (Hover (15, 25));
  emit sys (Click (30, 40));
  emit sys (KeyPress 'a');

  Printf.printf "Total clicks: %d\n" !click_count