例外処理 in common lisp
Exception in common lisp.
Introduction
Common Lispでの例外処理は難しくないよ、というお話。
仮に難解だとしてもそれはCommon Lisp固有の難解さではなく例外処理固有の(すなわち他言語であっても同様の)難解さでしょう。
Syntax.
以下にC++での例外処理コードをwikipediaから引用します。
C++以外の言語でも構文としてはおよそ変わらないでしょう。
void Function0(void) throw(...) // (2)
{
// (1)
throw 0;
throw "message";
throw std::runtime_error( "message" );
throw;
}
void Function1(void)
{
try
{
Function0();
}
catch( int exception ) // (3)
{
// 回復処理
}
catch( char const *exception ) // (4)
{
// 回復処理
}
catch( std::exception const &exception ) // (5)
{
// 回復処理
}
catch(...) // (6)
{
// 回復処理
throw; // (7)
}
}
Common Lispではだいたい以下のようになります。
(defun function0 ()
(error "message"))
(defun function1 ()
(handler-case (function0)
(error (c) ;; 回復処理
)))
try
〜catch
の構文がHANDLER-CASE
というマクロにまとめられているのが見て取れます。
Issue about keywords differences.
それでもCommon Lispの例外処理が難解なものに見えてしまう原因の一つに名前の異なりが挙げられます。
多くの言語で「例外」と呼ばれるものはCommon LispではCONDITION
と呼ばれます。
「例外」はthrow
されるものですが、CONDITION
はSIGNAL
されるものです。
try
〜catch
構文がHANDLER-CASE
になるのは前節で示したとおりです。
ややこしいのはCommon LispにはTHROW
もCATCH
も存在していることです。
しかもそれは例外処理とは実質関係がありません。
Common Lispで例外処理をするにあたり、他言語での経験からTHROW
やCATCH
にたどり着いても、それは欲しいものではなく、では何で検索をすれば欲しい情報にたどりつけるかというとそれがさっぱり分からない(想像がつかない)、というのが難解さの要因となっているのではないかと愚考する次第。
References
CLHS
CONDITION
に関する言語仕様はCLHSで。
Condition system as library.
Common Lispのコンディション機構は言語のコア上にライブラリとして実装できます。
実際に行っているのがPortable Condition Systemです。
QL:QUICKLOAD
でインストール可能です。
Book
上のPORTABLE-CONDITION-SYSTEM
の作者によって書かれたコンディション機構をテーマに書きあげた書籍がこちら。
Japanese
実践Common Lispは数ある邦訳Common Lisp書籍のなかでも唯一コンディション機構に詳しい書籍です。
英語に抵抗ない方は公開されているのでそちらを読むのも良いでしょう。
Blog
手前味噌ながら以前コンディション機構の大半を自前で実装しながら解説を試みたことがあるでよろしければどうぞ。
Discussion