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

これもおおよそ一緒のタイプの問題。書き換えでできる。

やることはちょっと変わる。

  • let->combinationに振り分け機能
  • named-let-clauses手続き
  • named-let-bindings手続き(ここまでparameterってしてたよ。)
  • named-let-body手続き
  • expand-named-let-clauses手続き

まず、書き換えを行ってみる。
こいつが、、、

(define (fib n)
  (let fib-iter ((a 1)
                 (b 0)
                 (count n)) 
    (if (= count 0)
      b   
      (fib-iter (+ a b) a (- count 1)))))

こうなる、、、

(define (fib n)
  (define (fib-iter a b count)
    (if (= count 0)
      b   
      (fib-iter (+ a b) a (- count 1))))
  (fib-iter 1 0 n)) 

defineで書き換えた方がなんか慣れたかんじだな。
あとは、書き換え。定義と実行の2工程に別れているので、make-beginを使う。
make-defineってないから、自分でdefineのリストを作る。


実装

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


;;フィボナッチってなんだっけ?
(define (fib n)
  (if (= n 0) 0
    (if (= n 1) 1
    (+ (fib (- n 2)) (fib (- n 1))))))


;;4.8に載っている
(define (fib n)
  (let fib-iter ((a 1)
                 (b 0)
                 (count n))
    (if (= count 0)
      b
      (fib-iter (+ a b) a (- count 1)))))


;;iterをつかう
(define (fib n)
  (define (fib-iter a b count)
    (if (= count 0)
      b
      (fib-iter (+ a b) a (- count 1))))
  (fib-iter 1 0 n))


;;;実装
(load "./modules/4th.scm")
(load "./modules/let.scm")

(define (let->combination exp)
  (if (pair? (car (let-clauses exp)))
      (expand-let-clauses (let-clauses exp))
      (expand-named-let-clauses (let-clauses exp))))

(define (named-let-var clauses) (car clauses))

(define (named-let-bindings clauses) (cadr clauses))

(define (named-let-body clauses) (caddr clauses))

(define (expand-named-let-clauses clauses)
  (make-begin
    (list
      (list 'define (cons (named-let-var clauses)
                          (map car (named-let-bindings clauses)))
            (named-let-body clauses))
      (cons (named-let-var clauses)
            (map cadr (named-let-bindings clauses))))))

(define the-global-environment (setup-environment))
(driver-loop)


実行

;;; M-Eval input:
(define (fib n)
  (let fib-iter ((a 1)
                 (b 0)
                 (count n)) 
    (if (= count 0)
      b   
      (fib-iter (+ a b) a (- count 1)))))

;;; M-Eval value:
ok

;;; M-Eval input:
(fib 10)

;;; M-Eval value:
55