Common Lispブロックはcatch
とthrow
にとても
類似している非局所脱出メカニズムを適用するが、それは動的
スコープではなくレキシカルスコープである。このパッケージは実際には
catch
でblock
を実装する; しかし、ブロック本体が実際には
ブロックからreturn-from
しない場合、レキシカルスコープは最適化
バイトコンパイラが高価なcatch
を省略することを許す。
formsはprogn
によるかのように評価される。しかし、
formsのいずれかが(return-from name)
を実行する場合、
それらは飛び出してblock
フォームからダイレクトに戻る。
block
は、return-from
が起こらないと最後のformの結果
を戻す。
block
/return-from
メカニズムはcatch
/throw
メカニズムと非常に類似している。主要な相違は、ブロックnameは
評価されないシンボルであり、実行時にタグへと評価するフォーム
(引用符のついたシンボルのように)ではない点である; そしてまた、
ブロックはcatch
/throw
では動的スコープであるのに
レキシカルスコープである。これは、catch
の本体から呼び出された
関数もcatch
へthrow
できるが、ブロック名を参照する
return-from
は物理的にブロックの本体を作るformsの中に
現れなければならないことを意味する。それらは他の呼び出された関数中に
現れてはならないが、マクロ展開の中や本体のlambda
に
現れてもよい。ブロック名やcatch
名は独立した名前空間を形成する。
真のCommon Lispでは、defun
やdefmacro
は関数やマクロと同じ
名前を持つ暗黙のブロックで関数やエクスパンダ本体を囲む。これはEmacs
Lispでは起こらないが、このパッケージは暗黙のブロックを作る
defun*
やdefmacro*
フォームを提供する。
このパッケージによって定義される、loop
やdolist
のような
Common Lispループ構文要素も、Common Lispとちょうど同様の暗黙のブロック
を作る。
それらはEmacs Lispのcatch
やthrow
で実装されているので、
ブロックは実際のcatch
構文要素と同じオーバーヘッド(大まかに2度の
関数呼び出し)を持つ。しかし、ZawinskiとFurusethの最適化
バイトコンパイラ(Emacs 19の標準)は、ブロックが事実まったくそれへ
飛び出すreturn
やreturn-from
呼び出しを含まない場合、
catch
を最適化し去る。これは、return
を使わないdo
ループやdefun*
関数はそれをサポートするためにオーバーヘッドを
払わないことを意味する。
このマクロはnameという名前のブロックから戻る。nameは
(評価されない)シンボルでなければならない。resultフォームが
指定される場合、block
から戻される結果を作るために評価される。
そうでなければ、nil
が戻される。
このマクロは(return-from nil result)
と正確に同等である。
do
やdolist
のようなCommon Lispループは暗黙にnil
ブロックに自身を囲む。