Advanced Pattern Matching

The compiler builds efficient decision trees / jump tables; matching on constructors is O(1)-ish.

25.1 Guards and or-patterns with bindings

let classify = function
  | (0, y) | (y, 0) -> Printf.sprintf "on an axis at %d" y   (* both sides bind y *)
  | (x, y) when x = y -> "diagonal"
  | _ -> "elsewhere"

25.2 Matching on records, arrays, and nested structures

type event = { kind : [`Click | `Key of char]; pos : int * int }

let handle = function
  | { kind = `Click; pos = (0, 0) } -> "click at origin"
  | { kind = `Key ('q' | 'Q'); _ } -> "quit"
  | { kind = `Key c; _ } -> "key " ^ String.make 1 c
  | { kind = `Click; pos = (x, _) } when x < 0 -> "offscreen"
  | _ -> "other"

let first_two = function [| a; b |] -> a + b | _ -> 0

25.3 Pattern matching on exceptions and effects

match f () with
| v -> Ok v
| exception (Failure msg) -> Error msg
(* OCaml 5.3+: | effect E, k -> ...   see §35 *)

25.4 Refutation cases (.) — prove a case is impossible (used with GADTs)

type _ tag = I : int tag | S : string tag

let only_int (x : int tag) : int = match x with
  | I -> 0
  | _ -> .          (* "this case is unreachable" — checked by the compiler *)

25.5 match vs function vs let destructuring

let (a, b) = ... — single irrefutable pattern.

function — anonymous function matching its argument.

match ... with — general.

25.6 Compilation of pattern matching

The compiler builds efficient decision trees / jump tables; matching on constructors is O(1)-ish. Don't hesitate to use deep patterns for performance reasons.