Next: , Previous: , Up: 制御構造   [Contents][Index]


4.5 ブロックと脱出

Common Lispブロックcatchthrowにとても 類似している非局所脱出メカニズムを適用するが、それは動的 スコープではなくレキシカルスコープである。このパッケージは実際には catchblockを実装する; しかし、ブロック本体が実際には ブロックからreturn-fromしない場合、レキシカルスコープは最適化 バイトコンパイラが高価なcatchを省略することを許す。

Special Form: block name forms…

formsprognによるかのように評価される。しかし、 formsのいずれかが(return-from name)を実行する場合、 それらは飛び出してblockフォームからダイレクトに戻る。 blockは、return-fromが起こらないと最後のformの結果 を戻す。

block/return-fromメカニズムはcatch/throw メカニズムと非常に類似している。主要な相違は、ブロックnameは 評価されないシンボルであり、実行時にタグへと評価するフォーム (引用符のついたシンボルのように)ではない点である; そしてまた、 ブロックはcatch/throwでは動的スコープであるのに レキシカルスコープである。これは、catchの本体から呼び出された 関数もcatchthrowできるが、ブロック名を参照する return-fromは物理的にブロックの本体を作るformsの中に 現れなければならないことを意味する。それらは他の呼び出された関数中に 現れてはならないが、マクロ展開の中や本体のlambdaに 現れてもよい。ブロック名やcatch名は独立した名前空間を形成する。

真のCommon Lispでは、defundefmacroは関数やマクロと同じ 名前を持つ暗黙のブロックで関数やエクスパンダ本体を囲む。これはEmacs Lispでは起こらないが、このパッケージは暗黙のブロックを作る defun*defmacro*フォームを提供する。

このパッケージによって定義される、loopdolistのような Common Lispループ構文要素も、Common Lispとちょうど同様の暗黙のブロック を作る。

それらはEmacs Lispのcatchthrowで実装されているので、 ブロックは実際のcatch構文要素と同じオーバーヘッド(大まかに2度の 関数呼び出し)を持つ。しかし、ZawinskiとFurusethの最適化 バイトコンパイラ(Emacs 19の標準)は、ブロックが事実まったくそれへ 飛び出すreturnreturn-from呼び出しを含まない場合、 catchを最適化し去る。これは、returnを使わないdo ループやdefun*関数はそれをサポートするためにオーバーヘッドを 払わないことを意味する。

Special Form: return-from name [result]

このマクロはnameという名前のブロックから戻る。nameは (評価されない)シンボルでなければならない。resultフォームが 指定される場合、blockから戻される結果を作るために評価される。 そうでなければ、nilが戻される。

Special Form: return [result]

このマクロは(return-from nil result)と正確に同等である。 dodolistのようなCommon Lispループは暗黙にnil ブロックに自身を囲む。