level 13
loop
プログラムの制御で重要な要素である繰り返しを行うには、LISP 言語の場合はいくつかの方法があります。 簡単なループを作成するには loop マクロを利用します。 loop マクロは、指定した任意の数の式を無限ループで実行します。
loop {form}*
form に任意の数の式を指定します。 loop マクロが実行されると、式を最初から順番に実行し、全ての実効が終わるとそのまま最初に戻って実行します。 この状態だと無限ループに陥ってしまうため、return または return-from 特別式を用いて loop から抜け出すことができます。 loop は nil のブロックのようなものなので、return または return-from nil で抜け出すことができます。
特別な理由がない限り、loop マクロのどこかでブロックを抜け出す条件を指定しなければなりません。 if などを用いて、変数用カウンタを調べ、条件が整っている場合は return を実行するという方法になるでしょう。
2011年11月08日 12点11分
2
level 13
> (setq i 10)
> (setq x nil)
> (loop
(if (= i 0) (return i))
(setq x (cons i x))
(setq i (- i 1))
)
0
> x
(1 2 3 4 5 6 7 8 9 10)
このコマンドでは、カウンタ用の変数 i を 10 で初期化し、ループを実行するたびにデクリメントして、現在の i の変数を 1 ずつ減らしていきます。 最初の式で i が 0 であるかどうかを調べ、カウンタが 0 になっていれば return を実行してループを抜け出すように仕組んでいます。 繰り返し処理ではリスト x に cons を用いて i を追加するようにプログラムしています。 最後に x の値を確認すれば、繰り返し処理によってリストが正しく作られていることを確認することができます。
ループ処理が特別式ではなくマクロで実装されているのは、プログラムの特殊な文法を持ちいらなくても、block、tagbody、go の組み合わせて繰り返し処理を実現することができるためです。 例えば、上記の loop マクロによるプログラムは以下のように記述することもできます。
2011年11月08日 12点11分
3
level 13
> (setq i 10)
10
> (setq x nil)
NIL
> (block nil
(tagbody
loop (if (= i 0) (return 0))
(setq x (cons i x))
(setq i (- i 1))
(go loop)
)
)
0
> x
(1 2 3 4 5 6 7 8 9 10)
繰り返し処理の仕組みは、tagbody の末尾で go を用い、tagbody の先頭にジャンプしていることで実現しています。 その結果、条件が t になるまで tagbody が繰り返されるのです。
-------------------------------------------------------------------------------------------------------
2011年11月08日 12点11分
4