Caml では例外的状況を通知し、処理するために例外機構が提供されています。
例外は汎用の大域制御構造として使うこともできます。
例外は exception で宣言され、raise で通知します。例として、リストの先頭を返す関数を示します。この関数は空リストを渡されたとき例外を通知します。
#exception Empty_list;;exception Empty_list#let head l = match l with [] -> raise Empty_list | hd :: tl -> hd;;val head : 'a list -> 'a = <fun>#head [1;2];;- : int = 1#head [];;Exception: Empty_list.
標準ライブラリの関数は正常に処理を完了できなかったとき例外を通知します。たとえば List.assoc は、(key, data) というペアのリストから、与えられたキーに該当するデータを返す関数ですが、キーがリストから見つからなかったとき、定義済みの例外 Not_found を発生させます。
#List.assoc 1 [(0, "zero"); (1, "one")];;- : string = "one"#List.assoc 2 [(0, "zero"); (1, "one")];;Exception: Not_found.
例外は try...with 構文で捕捉することが出来ます。
#let name_of_binary_digit digit = try List.assoc digit [0, "zero"; 1, "one"] with Not_found -> "not a binary digit";;val name_of_binary_digit : int -> string = <fun>#name_of_binary_digit 0;;- : string = "zero"#name_of_binary_digit (-1);;- : string = "not a binary digit"
with の部分は、実際には例外の値に対するパターンマッチングです。したがって 1 つの try...with で複数の例外を捕捉することが出来ます。さらに、すべての例外を捕捉して終了処理をし、例外を再度発生させることで終了処理をすることができます。
#let temporarily_set_reference ref newval funct = let oldval = !ref in try ref := newval; let res = funct () in ref := oldval; res with x -> ref := oldval; raise x;;val temporarily_set_reference : 'a ref -> 'a -> (unit -> 'b) -> 'b = <fun>