progn 特別式


複数の式を評価する

if 特別式によって、条件に応じて評価する式を分岐させることができるようになりました。 対象の式が単一である場合は問題ありませんが、しかし if によって分岐させて評価する式が複数存在した場合する場合は、if 特別式に式を直接書くだけでは実現できません。

例えば、変数 m が t であれば、式1と式2を実行し、そうでなければ式3と式4を実行しなければならないというような場合です。 条件の結果によって複数の式を評価したいのですが、if が評価する式は任意の数ではなく、一つの式だけです。

複数の式を一度に評価させなければならない場合は progn 特別式を利用します。 progn 特別式は、任意の数の引数を受付、先頭の引数から順に全ての式を評価します。

progn {form}*

progn に対して、引数となる式を複数与えた場合、先頭から全ての式が評価されますが、この特別式の結果となるのは最後に評価された式のみです。 その他の式は結果に反映されないため、通常は何らかの副作用を持つ(変数への代入など)式となるでしょう。 progn に引数を何も与えなかった場合、progn 特別式は何も評価せずに nil を返します。

> (progn 10 20 30)
30
> (progn (setq x 10) (setq y 20) (setq z 30))
30
> x
10
> y
20
> z
30

最初の progn 特別式の実行では定数 10、20、30 を評価していますが、progn の戻り値となるのは最後に評価された式である 30 のみで、10 と 20 は何の意味もありません。 そのため、通常はその次の progn のように、変数に値を代入するなど、評価結果に何らかの副作用が持たされる式を指定します。

これを if 特別式で評価させれば、条件の結果によって複数の式を実行するということが可能になります。 つまり (if 条件 (progn ...) (progn ...)) というような形です。

条件の結果によって複数の式を実行する方法として if と progn の組み合わせを解説しましたが、実はこれを一度に行ってくれる when マクロがあります。 when マクロは任意の数の引数を受けることができる if のようなものだと考えてください。

when test {form}*

これは、単に (if test (progn form...)) と同じです。 式 test を条件として、条件の結果が nil でなければ、任意の数の式である form を逐次評価します。 そして、progn 同様に最後に評価した式を when の結果として返します。

when と逆の働きをする unless マクロも存在します。 これは、条件式が nil であれば、それ以降の式を評価するというマクロで、(when (not test) form ...) と同じ効果を持ちます。

unless test {form}*

筆者は、プログラミング言語が提供する機能は最小限にとどめ、複雑な命令は単純な命令の組み合わせて実現されるべきだと思っているので、unless を使うよりも when not を比較的好んでいます。 これは、どちらを使っても意味は同じなので、プログラマの好みの問題です。



前のページへ戻る次のページへ