×

×は掛け算だ。o* と書くことにしよう。n×m を言い換えると、nをm回足したものということができる。だから o* を定義するには、m を0になるまで1ずつ減らしながら、nを足していけばいい。1ずつ減らしていくのは (sub1 m) で、最終条件は (zero? m) だ。

第4の戒律
(改訂版)
再帰の間は少なくとも1つの引数を常に変化させるべし。引数は終わりに向けて変化させることを要す。変化する引数は最終条件にてテストすべし。すなわち、cdr を用いるときは、null? で最終テストし、sub1 を用いるときは、zero? で最終テストせよ。

それじゃ、関数 o* を書いてみよう。

(define add1
  (lambda (n)
    (+ n 1)))

(define sub1
  (lambda (n)
    (- n 1)))

(define o+
  (lambda (n m)
    (cond
      ((zero? m) n)
      (else (add1 (o+ n (sub1 m)))))))

(define o*
  (lambda (n m)
    (cond
      ((zero? m) 0)
      (else (o+ n (o* n (sub1 m)))))))

(print (o* 2 3))
(print (o* 10 5))

実行:

^o^ > gosh mul.scm
6
50

21行目、(zero? m) のときの値が 0 なのは、0 が足し算の答に影響しないからだ。もし再帰に掛け算を使うとすれば、0 の換わりに 1 を使えばいい。

第5の戒律
+で値を作らんとせしときは、行を終えるときに常に値として 0 を用うべし。なんとなれば、0 を加うるは加算の値を変えぬからなり。
×で値を作らんとせしときは、行を終えるときに常に値として 1 を用うべし。なんとなれば、1 を掛けるは乗算の値を変えぬからなり。
cons で値を作らんとせしときは、行を終えるときに常に値として () を考えるべし。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください