do式
do式は,同じ式を繰り返し(ループ)実行するための機能を提供する. 自己末尾再帰呼出しで記述できる関数は,このdo式を用いて再帰呼出しをしない 形に書き換えることができる.do式の構造は以下の通り.
(do ((<変数1> <初期値1> <ステップ1>) (<変数2> <初期値2> <ステップ2>) : (<変数n> <初期値n> <ステップn>)) (<終了条件> <式e1> <式e2> … <式ek>) <式l1> <式l2> : <式lm>)do式では,<変数1>...<変数n>を用いて,<終了条件>が成り立つまで,ループの本体<式l1>...<式lm>を繰り返し評価する.
具体的な評価手順は以下の通り.
- まず<初期値1>...<初期値n>が評価され,対応する各変数に代入される.
- 次に<終了条件>が評価される.
- 結果が#fであれば,ループの本体<式l1>...<式lm>が順次評価される. ループは空(式の個数が0)でもよい.
- ループの評価が終わると,<ステップ1>...<ステップn>が評価され,対応する各変数に代入される. つまり<ステップ>は,ループごとの変数の更新方法を表す.
- 次に更新された変数を用いて,再び<終了条件>が評価される. 結果が#fであれば,上で述べたようなループが繰り返し実行される.
- <終了条件>の評価が真であれば(#fでなければ),そのすぐ後ろの式<式e1>...<式ek>が評価され,最後の<式ek>の値を返してdo式の評価が終了する. 式の個数は0でもよいが,その場合のdo式の評価値は仕様上は不定であり,システムの実現方法に依存する.
累乗を計算する関数をdo式を用いて書けば,以下のようになる.
(define (expt-do x n) (do ((i 0 (+ i 1)) ;; 局所変数i : ループ実行の回数を制御する (y 1)) ;; 局所変数y : 累乗の途中結果を保存する ((= i n) y) ;; 終了条件 : i = nのとき,yを返す (set! y (* x y)))) ;; ループ本体 : yに,x・yを代入するこの例の変数yの節に見られるように<ステップ>は省略可能である.その 場合には,(<変数> <初期値> <変数>)と書くのと同等の意味 になる.つまり,一回のループの評価が終わった時点での<変数>の値が次 のループで使われる.
なお,<初期値1>...<初期値n>および<ステップ 1>...<ステップn>の評価の順序は,仕様上は不定であり,シス テムの実現方法に依存する.