×は掛け算だ。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 で値を作らんとせしときは、行を終えるときに常に値として () を考えるべし。