問題1-30〜31

今日は、「高階手続きによる抽象」を体感するために、問題1-30〜31に取り組みました。問題1-31は、分母と分子それぞれの規則性を捉えつつ、それをカウンタごとに割ってやる手続きをどうやって書くかに手間取ってしまいましたが、何とか円周率に近そうな値を出せるコードを書くことができました。
まずは、sum手続きを線形再帰ではなく反復的に実行するための手続きです。(問題1-30)

(define (sum term a next b)
  (define (iter a result)
    (if (> a b)
        result
        (iter (next a) (+ result (term a)))))
  (iter a 0))
        
(define (cube x) (* x x x))

(define (inc n) (+ n 1))

(define (sum-cubes a b)
  (sum cube a inc b))

(sum-cubes 1 10)

=>3025

次は、「与えられた範囲の点での関数値の積を返す」product手続きです。10!でも、かなり大きな数になることが驚きでした。(問題1-31/上段が再帰的なプロセスで、下段が反復的なプロセス)

(define (product term a next b)
  (if (> a b)
      1
      (* (term a)
         (product term (next a) next b))))

(define (product term a next b)
  (define (iter a result)
    (if (> a b)
        result
        (iter (next a) (* result (term a)))))
  (iter a 1))

(define (inc n) (+ n 1))

(define (identity x) x)

(define (factorial n)
  (product identity 1 inc n))

(factorial 1)
(factorial 2)
(factorial 3)
(factorial 4)
(factorial 5)
(factorial 6)
(factorial 7)
(factorial 8)
(factorial 9)
(factorial 10)

=>1
=>2
=>6
=>24
=>120
=>720
=>5040
=>40320
=>362880
=>3628800

最後が、円周率の近似値を計算するproduct手続きです。小数点以降は分数として表示されてしまいましたが、3.14っぽい結果が返ってきました。(同じく、問題1-31)

(define (product term a next b)
  (define (iter a result)
    (if (> a b)
        result
        (iter (next a) (* result (term a)))))
  (iter a 1))

(define (inc n) (+ n 1))

(define (pi-term n)
  (/ (pi-a n) (pi-b n)))

(define (pi-a n)
  (if (= (remainder n 2) 1)
      (+ n 1)
      (+ n 2)))

(define (pi-b n)
  (if (= (remainder n 2) 0)
      (+ n 1)
      (+ n 2)))

(define (pi-product from to)
  (* 4 (product pi-term from inc to)))

(pi-product 1 1000)