計算機プログラムの構造と解釈 第二版 P34 問題1.32

やばい、思ったより簡単だった。
もちろん、間違ってるかもだけど。


これは、前に出てきてるsumとproductをさらに、accumulateという関数で
抽象化できませんか?という問題。


抽象化をどうやって考えるかといえば、
ざっくり、今まで固定値だった部分を、パラメータにしてやればいい。


んで、sumとproductの例で考えると、
sumからproductを作ったときには、「+」を「*」にしました。
sumからproductを作ったときには、終了の判定のあと返す値を「0」から「1」にしました。


と考えると、この二つをパラメータにして渡してやれば抽象化できそう。


与えられている式が

(accumulate combiner null-value term a next b)

となっていて、sumの時は

(sum term a next b)

だったから、
「term」 「a」 「next」 「b」はこのままでいいとして、
あとは、
sumの時、「*」になっていたところを「combiner」に
sumの時、「0」だったところを「null-value」に変えてやればいい


のではないかな?


あとは再帰的なのも、反復的なのも考え方はいっしょ!!
もうそこはほとんど問題にならぬ!!


そしてさらっとやってみた結果がこれだ!!
例として、1から10までの足し算と、5の階乗の計算をやってみた。

#!/usr/local/bin/gosh
;; -*- coding: utf-8 -*-

(use ggc.debug.trace)
(use math.mt-random)

(define (inc x)
  (+ 1 x)) 

(define (donothing x)
  x)  

;;再帰的プロセス
(define (accumulate combiner null-value term a next b)
  (if (> a b)
    null-value
    (combiner (term a)
              (accumulate combiner null-value term (next a) next b))))

;;反復的プロセス
(define (accumulate-r combiner null-value term a next b)
  (define (iter a result)
    (if (> a b)
      result
      (iter (next a) (combiner result (term a)))))
  (iter a null-value))


;; main
(define (main args)
  (display "sum (ex. add 1 to 5)  made by accumulate : ")
  (display (accumulate + 0 donothing 0 inc 10))(newline)
  (display "product (ex. 5!)  made by accumulate : ")
  (display (accumulate * 1 donothing 1 inc 5))(newline)(newline)

  (display "sum (ex. add 1 to 5)  made by accumulate-r : ")
  (display (accumulate-r + 0 donothing 0 inc 10))(newline)
  (display "product (ex. 5!)  made by accumulate-r : ")
  (display (accumulate-r * 1 donothing 1 inc 5))(newline)
)


実行

sum (ex. add 1 to 5)  made by accumulate : 55
product (ex. 5!)  made by accumulate : 120

sum (ex. add 1 to 5)  made by accumulate-r : 55
product (ex. 5!)  made by accumulate-r : 120

さらっとできたので、むしろちょっと不安です。