do-loop の終了判定タイミング
do でループさせる処理を書いていて、思った通りの箇所でループを抜けずにいろいろ試してみた。どうやら、ループ内で使用する変数の初期化処理があると、それを行うまで判定処理が実行されないらしい。時系列で整理すると、
- do 内で使用する変数の初期化
- 終了判定
- メインの処理
- 最初に戻る
という流れのようだ。なので、仮に
- do 内で使用する変数の初期化
- メインの処理
- 終了判定
というようにしたい場合は、変数の初期化をメインの処理に含める必要がある。具体的には、
(do ((x (init-x-value) (init-x-value)) (y (init-y-value) (init-y-value))) ((finish-judgement-function)) (format t "~A~A~%" x y))
という書き方ではなく以下のようにする。
(do () ((finish-judgement-function)) (let ((x (init-x-value)) (y (init-y-value))) (format t "~A~A~%" x y)))
先の書き方だと、format 直後に finish-judgement-function が実行されず、function 直後には x と y の初期化が行われ、初期化後に finish-judgement-function が実行される。後者のようにすると、format 直後に finish-judgement-function が実行され、C言語の do { } while () のような状態になる。