progn は一連の式順次評価するために利用することができる特別式でしたが、全てのケースで無条件に全ての式を実行することが許容されるわけではありません。 例えば、条件に応じて式の実行を中断しなければならないという場合があるでしょう。
C言語のような手続き型言語には内側のスコープを定義するブロックの概念がありますが、LISP 言語にもこれに似たブロック構造と呼ばれる概念が存在します。 ブロックを定義するには block 特別式を用います。 block 特別式によるブロックは progn のように、任意の数の式を評価しますが、必要に応じて途中で中断することができます。
block name {form}*
name には、このブロックの名前を指定します。 block は特別式なので、ブロック名には直接記号を指定することができます。 ブロック名の後の form には、任意の数の式を指定することができます。 block の値は最後に評価された式の値となります。
block のスコープ内であれば、ブロック名を用いてブロックの評価を中断することができます。 評価を中断してブロックを抜け出すには return-from 特別式を使います。
return-from name [result]
name には中断する対象のブロック名を、result にはブロックの結果となる値を指定します。 name は、記号を指定しても記号が評価されることはないので、記号を直接指定することができます。 result を省略した場合は NIL が結果となります。
> (block test 1 10 100) 100 > (block test 1 (return-from test 10) 100) 10 > (block test 1 (return-from test) 100) NIL
block は return-from を指定しなければ、progn 同様に式を順次評価します。 最初の block はそのまま数値を指定しているため、最後に評価された式 100 が block の結果となります。 これに対して、2回目の block は return-from 特別式で block を中断しているため、return-from で指定したブロックの値 10 が結果となります。
また、return-from のブロック名を省略した return マクロも用意されています。 このマクロは (return-from nil result) と同義です。
return [result]
result にはブロックの値を指定します。 名前は常に nil が指定されたものと解釈されます。
> (block nil 1 (return 10) 100) 10
この block の名前は nil なので、return-from nil または return でこのブロックの名前を指定することができます。
block が階層的な入れ子になっても、名前によって識別できるため、どのブロックを中断するのかを明示的に指定することができます。 そのため、内側のブロックから一気に外側のブロックの評価も含めて中断することができます。
> (block outside (block inside (return-from outside 10) 100) 1000) 10
このブロックでは outside と inside のブロックが入れ子になっています。 inside ブロック内で return-from を用いて、中断対象のブロックを outside に指定しています。 そのため、この式が実行された時点でブロック全体が終了して 10 が結果として返されるという仕組みです。