Schemeで繰り返しを行う

※ 以下はScheme初心者である私の勉強用のメモです。

間違っている可能性がありますので注意してください。

do式

 do式を使用することで繰り返しを行うことができる。ただし、Schemeでは繰り返しを再帰を使って書くのが一般的なようである。

一般形
(do ((変数1 初期値1 ステップ1)
     (変数2 初期値2 ステップ2)
     (・・・ ・・・ ・・・)
     (変数n 初期値n ステップn))
  (ループ終了条件 ループ終了後に返す値)
  式・・・)

 一見するとC言語のfor文に似ているのだが、似て非なる構文をしている。do式は、変数1から変数nまでをローカル変数として、ループ終了条件が真になるまで処理を繰り返す。do式の動作をまとめると以下のようになる。

do式の動作

ループ1回目

  • [初期値1]から[初期値n]までが評価され、その値が[変数1]から[変数n]にバインドされる。
  • [ループ終了条件]が評価され、偽であれば[式・・・・]部分を実行する。


ループ2回目以降

  • [ステップ1]から[ステップn]までが評価され、その値が[変数1]から[変数n]にバインドされる。
  • [ループ終了条件]が評価され、偽であれば[式・・・・]部分を実行する。
なお、当たり前のことだが、ループ終了条件はあくまで終了条件である。C言語のfor文のように継続条件ではない。

例1
;xのn乗を計算する その1
(define (power x n)
    (if (= n 0)
        1
        (do ((i 1 (+ i 1))
             (ans x (* ans x)))
          ((>= i n) ans))))

; 実行例
> (power 3 0)
1
> (power 3 1)
3
> (power 3 2)
9
> (power 3 3)
27

上記の例はlet式とset式を使って強引に以下のように書くことが出来る。

例2
;xのn乗を計算する その2
(define (power2 x n)
  (let ((ans x))
    (if (= n 0)
        1
        (do ((i 1 (+ i 1)))
          ((>= i n) ans)
          (set! ans (* ans x))))))

; 実行例
> (power2 3 0)
1
> (power2 3 1)
3
> (power2 3 2)
9
> (power2 3 3)
27