๐Ÿฆ€ Functional Rust
๐ŸŽฌ Pattern Matching Exhaustive match, destructuring, guards, let-else โ€” compiler-verified branching.
๐Ÿ“ Text version (for readers / accessibility)

โ€ข match is exhaustive โ€” the compiler ensures every variant is handled

โ€ข Destructuring extracts fields from structs, tuples, and enums in one step

โ€ข Guards (if conditions) add extra logic to match arms

โ€ข if let and let-else provide concise single-pattern matching

โ€ข Nested patterns and @ bindings handle complex data shapes elegantly

592: Command Pattern as Data

Difficulty: 3 Level: Intermediate Encode operations as enum variants so they can be queued, replayed, undone, or logged โ€” separating intent from execution.

The Problem This Solves

In most codebases, "do X" and "doing X right now" are the same thing โ€” you call the function and it runs immediately. This is fine until you need to queue operations for later, replay a sequence of actions, implement undo/redo, log what happened for audit, or synchronize state between distributed nodes. The functional command pattern decouples describing an operation from executing it. Commands are enum variants โ€” plain data. They can be stored in a `Vec`, sent over a channel, serialized to disk, filtered, or inspected before execution. The executor is a separate function that pattern-matches on variants. This is the foundation of event sourcing (your database is a log of commands), CQRS (commands and queries are separate), undo/redo systems (maintain a history stack), and remote procedure calls (serialize the command, send it, execute on the other side).

The Intuition

When a command is data (an enum variant), "now" vs "later" is just a matter of when you pass it to the executor โ€” the operation itself is fully described, storable, and inspectable before it runs. The trade-off: you add a layer of indirection (describe then execute) which costs a little in simplicity but gains enormous flexibility.

How It Works in Rust

use std::collections::VecDeque;

// Commands are data โ€” fully described, no side effects yet
#[derive(Debug, Clone)]
enum EditorCommand {
 InsertChar { pos: usize, ch: char },
 DeleteChar { pos: usize },
 MoveCursor { delta: i32 },
}

struct Editor {
 text: String,
 cursor: usize,
 history: Vec<EditorCommand>,    // undo stack
}

impl Editor {
 fn execute(&mut self, cmd: EditorCommand) {
     self.history.push(cmd.clone());   // record before executing
     match cmd {
         EditorCommand::InsertChar { pos, ch } => self.text.insert(pos, ch),
         EditorCommand::DeleteChar { pos } => { self.text.remove(pos); }
         EditorCommand::MoveCursor { delta } => {
             self.cursor = (self.cursor as i32 + delta).max(0) as usize;
         }
     }
 }

 fn undo(&mut self) {
     if let Some(cmd) = self.history.pop() {
         // apply inverse โ€” commands are data so we can reason about inverses
         match cmd {
             EditorCommand::InsertChar { pos, .. } => { self.text.remove(pos); }
             EditorCommand::DeleteChar { pos } => { /* restore from somewhere */ }
             _ => {}
         }
     }
 }
}

// Commands can be queued, replayed, filtered
let mut queue: VecDeque<EditorCommand> = VecDeque::new();
queue.push_back(EditorCommand::InsertChar { pos: 0, ch: 'H' });
queue.push_back(EditorCommand::InsertChar { pos: 1, ch: 'i' });

What This Unlocks

Key Differences

ConceptOCamlRust
Command as valueVariant type`enum` variant
UndoInverse variant or deltaInverse variant or stored old state
History queue`list` or `Queue.t``Vec` or `VecDeque`
Serialization`ppx_serde` / `ppx_yojson``#[derive(Serialize, Deserialize)]`
ExecutionPattern match function`match cmd { ... }` in executor method
ReplayRe-execute listIterate history and re-execute
#[derive(Debug,Clone)]
enum DrawCmd {
    MoveTo(f64, f64),
    LineTo(f64, f64),
    SetColor(String),
    SetWidth(f64),
}

#[derive(Debug,Default,Clone)]
struct DrawState {
    x: f64, y: f64,
    color: String,
    width: f64,
}

fn execute(state: &mut DrawState, cmd: &DrawCmd, log: &mut Vec<String>) {
    match cmd {
        DrawCmd::MoveTo(x,y)   => { state.x=*x; state.y=*y; }
        DrawCmd::LineTo(x,y)   => {
            log.push(format!("line ({:.1},{:.1})->({:.1},{:.1}) color={} w={}", state.x,state.y,x,y,state.color,state.width));
            state.x=*x; state.y=*y;
        }
        DrawCmd::SetColor(c)   => { state.color=c.clone(); }
        DrawCmd::SetWidth(w)   => { state.width=*w; }
    }
}

// Command macro: build sequences
fn rect(x: f64, y: f64, w: f64, h: f64) -> Vec<DrawCmd> {
    vec![
        DrawCmd::MoveTo(x,y),
        DrawCmd::LineTo(x+w,y),
        DrawCmd::LineTo(x+w,y+h),
        DrawCmd::LineTo(x,y+h),
        DrawCmd::LineTo(x,y),
    ]
}

fn replay(cmds: &[DrawCmd]) -> (DrawState, Vec<String>) {
    let mut state = DrawState { color:"black".into(), width:1.0, ..Default::default() };
    let mut log = Vec::new();
    for cmd in cmds { execute(&mut state, cmd, &mut log); }
    (state, log)
}

fn main() {
    let mut cmds = vec![DrawCmd::SetColor("red".into()), DrawCmd::SetWidth(2.0)];
    cmds.extend(rect(0.0, 0.0, 10.0, 10.0));
    let (final_state, log) = replay(&cmds);
    for l in &log { println!("{}", l); }
    println!("final pos: ({:.1},{:.1})", final_state.x, final_state.y);
    println!("total commands: {}", cmds.len());
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test] fn rect_cmds() { assert_eq!(rect(0.0,0.0,1.0,1.0).len(), 5); }
    #[test] fn replay_moves() {
        let cmds = vec![DrawCmd::MoveTo(3.0,4.0), DrawCmd::SetColor("blue".into())];
        let (s,_) = replay(&cmds);
        assert_eq!((s.x,s.y), (3.0,4.0));
    }
}
(* Command pattern as data in OCaml *)
type cmd =
  | MoveTo  of float * float
  | LineTo  of float * float
  | ArcTo   of float * float * float
  | SetColor of string
  | Undo

type point = { mutable x: float; mutable y: float }
type state = { pos: point; mutable color: string; mutable history: cmd list }

let mk_state () = { pos={x=0.;y=0.}; color="black"; history=[] }

let execute s cmd =
  (match cmd with
  | MoveTo(x,y)   -> s.pos.x<-x; s.pos.y<-y
  | LineTo(x,y)   -> Printf.printf "line (%.1f,%.1f)->(%.1f,%.1f)\n" s.pos.x s.pos.y x y;
                     s.pos.x<-x; s.pos.y<-y
  | ArcTo(x,y,r)  -> Printf.printf "arc to (%.1f,%.1f) r=%.1f\n" x y r;
                     s.pos.x<-x; s.pos.y<-y
  | SetColor c    -> s.color<-c
  | Undo          -> ());
  s.history <- cmd :: s.history

let () =
  let s = mk_state () in
  List.iter (execute s)
    [MoveTo(0.,0.); SetColor "red"; LineTo(10.,0.); LineTo(10.,10.); LineTo(0.,10.)]