🦉

例外処理 in common lisp

2021/07/13に公開

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) ;; 回復処理
      )))

trycatchの構文がHANDLER-CASEというマクロにまとめられているのが見て取れます。

Issue about keywords differences.

それでもCommon Lispの例外処理が難解なものに見えてしまう原因の一つに名前の異なりが挙げられます。

多くの言語で「例外」と呼ばれるものはCommon LispではCONDITIONと呼ばれます。
「例外」はthrowされるものですが、CONDITIONSIGNALされるものです。
trycatch構文がHANDLER-CASEになるのは前節で示したとおりです。

ややこしいのはCommon LispにはTHROWCATCHも存在していることです。
しかもそれは例外処理とは実質関係がありません。

Common Lispで例外処理をするにあたり、他言語での経験からTHROWCATCHにたどり着いても、それは欲しいものではなく、では何で検索をすれば欲しい情報にたどりつけるかというとそれがさっぱり分からない(想像がつかない)、というのが難解さの要因となっているのではないかと愚考する次第。

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