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
ブロックに自身を囲む。