例外は実用上とても有用ですが、例外を誤用したコードがよく見られることでも知られています。
一般的に言うと、プログラムの実行を中断終了させるために捕捉されないことを意図した例外と、プログラム実行の流れを変えるために (しばしばローカルで宣言した) 捕捉されることを意図した例外があります。 例えば、例外 ArraySubscriptExn は実行時に配列の範囲外を添字指定したことを検出すると発生します。 この例外が発生すると、通常 ArraySubscriptExn は捕捉されることを意図していません。 プログラマが ArraySubscriptExn 例外を捕捉するコードを書くことを妨げるものはなにもありませんが、そのコードが非常に複雑になってしまう懸念があります。 次に、発生した後に捕捉されることを意図した例外について説明しようと思います。
リストの中から与えられた述語を満たす一番右の要素を見つける関数を実装している次のコードを見てみましょう:
extern fun{a:t@ype} list_find_rightmost (List (a), (a) -<cloref1> bool): Option_vt (a) // implement{a} list_find_rightmost (xs, pred) = let // fun aux ( xs: List(a) ) : Option_vt (a) = case+ xs of | nil () => None_vt () | cons (x, xs) => let val res = aux (xs) in case+ res of | Some_vt _ => res | ~None_vt () => if pred (x) then Some_vt (x) else None_vt () // end of [None] end (* end of [cons] *) // in aux (xs) end // end of [list_find_rightmost]
implement{a} list_find_rightmost (xs, pred) = let // exception Found of (a) // fun aux ( xs: List(a) ) : void = case+ xs of | nil () => () | cons (x, xs) => let val () = aux (xs) in if pred (x) then $raise Found(x) else () end (* end of [cons] *) // in // try let val () = aux (xs) in None_vt () end with | ~Found(x) => Some_vt (x) // end // end of [list_find_rightmost]
例外を実行時にサポートする ATS の実装は alloca.h で宣言されている alloca 関数と setjmp.h で宣言されている setjmp と longjmp 関数を使っています。 ATS ソースコードから生成されたC言語ソースコードをコンパイルするのに gcc もしくは clang を使う場合、 alloca.h ヘッダファイルが確実にインクルードするために -D_GNU_SOURCE フラグを渡すことができます。
この章で紹介したコードの全体は オンライン から入手できます。