(sicp29)試しに先の方のことを読んでみた。

問題を解く気力あなかったので、先の方を読んでみました。
その時に、メッセージパッシングが理解できた気がしたので、
実際に、作ってみました。
その後、読んだだけの状態を記憶しておける関数も
作れる気がしたので作ってみることにしました。
そしたら、できてしまいました。
(たぶん、後で読むと何か勘違いしているのかもしれません><)

;;メッセージパッシングはたぶん理解した。
;;本当に理解したか確かめてみる。
;;四則演算する関数をメッセージパッシングでつくれたら、
;;本当に理解しているということにしておこう

(define (calc op x y)
  (define (add x y)
    (+ x y))
  (define (mul x y)
    (- x y))
  (define dispatch
    (let ((p? (lambda (x) (eq? op x))))
      (cond ((p? '+) (add x y))
            ((p? '-) (mul x y))
            (else
             (error "notfound" op)))))
  dispatch)
;;面倒なので"+", "-"だけでいいや
(calc '+ 1 2)
	;;1:user> => 3
;;できてるできてる


;;さらに状態を持ったcalcをつくろう.
;;その前に,accumulatorをつくろう.

(define (accumulator n)
  (let ((count n))
    (lambda (x)
    (set! count (+ count x)))))

(define acc (accumulator 30))
(acc 20)
;; 2:user> => acc
;; 3:user> => 50
;; 4:user> => 70
;; 5:user> => 90
;; 6:user> => 110
;; 7:user> => 130
;; 8:user> => 150

;;できた!
;;(50から先は、(acc 20)にカーソルを合わせてC-x eで評価を繰り返している)


;;accumulatorができたので、今度はcalc2
(define (calc2 init)
  (define (dispatch op)
    (let ((p? (lambda (it) (eq? op it))))
      (cond ((p? '+ ) add)
            ((p? '- ) mul)
            (else  (lambda (state x) state)))))
    (define (add m n) (+ m n))
    (define (mul m n) (- m n))
    (let ((state init))
      (lambda (op x)
        (set! state ((dispatch op) state x)))))

(define x (calc2 10))
(x '+ 10)
(x '+ 20)
(x '- 30)
(x '* 30)

;; 9:user> => x
;; 10:user> => 20
;; 11:user> => 40
;; 12:user> => 10
;; 13:user> => 10 
	;;"*"は定義されてないので、現在の値が帰ってくる