(sicp41)m3.33~m3.37

3.37のcopはmacroで作った方がいいのかもしれない。

;;m3.33
(define (averager a b c)
  (let ((double (make-connector))
        (ans (make-connector)))
    (multiplier double c ans)
    (adder a b ans)
    (constant 2 double))
  'ok)
(define A (make-connector))
(define B (make-connector))
(define C (make-connector))
(averager A B C)
(probe "A " A)
(probe "B " B)
(probe "average " C)
(set-value! A 30 'user)
(set-value! C 20 'user)
;; (set-value! B 30 'user)
;; (forget-value! C 'user)
;; (get-value B)


;;m3.34
(define (squarer a b)
  (multiplier a a b))
;;文字で指定しているし、回路を共有してしまっている。

;;m3.35
(define (squarer a b)
  (define (process-new-value)
    (if (has-value? b)
        (if (< (get-value b) 0)
            (error "squre less than 0 -- SQUARER" (get-value b))
            (set-value! a (sqrt (get-value b))  me))
        (set-value! b (* (get-value a) (get-value a)) me)))
  (define (process-forget-value)
    (forget-value! a me)
    (forget-value! b me)
    (process-new-value))
  (define (me request)
    (cond ((eq? request 'I-have-a-value)  
           (process-new-value))
          ((eq? request 'I-lost-my-value) 
           (process-forget-value))
          (else 
           (error "Unknown request -- SQUARER" request))))
  (connect a me)
  (connect b me)
  me)

(define A (make-connector))
(define B (make-connector))
(squarer A B)
(probe "A " A)
(probe "B " B)
(set-value! A 30 'user)
	;; Probe: A  = 30
	;; Probe: B  = 900=> done


;;m3.37
(define (celsius-fahrenheit-converter x)
  (c+ (c* (c/ (cv 9) (cv 5))
          x)
      (cv 32)))

(define (cop x y f)
  (let ((z (make-connector)))
    (f x y z)
  z))

(define (c+ x y)
  (cop x y
       (lambda (x y z) (adder x y z))))

(define (c- x y)
  ;;z = x - y
  ;;z + y = (x - y) + y = x
  (cop x y
       (lambda (x y z) (adder z y x))))

(define (c* x y)
  (cop x y
       (cut multiplier <> <> <>)))

(define (c/ x y)
  ;;z = x/y
  ;;z * y = (x/y) * y = x
  (cop x y
       (lambda (x y z) (multiplier z y x))))

(define (cv c)
  (let ((z (make-connector)))
    (constant c z)
    z))

(define C (make-connector))
(define F (celsius-fahrenheit-converter C))
(probe "C " C )
(probe "F " F)
(set-value! C 25 'user)
(forget-value! C 'user)
(set-value! F 212 'user)
	;; Probe: C  = 25
	;; Probe: F  = 77=> done
	;; 18:user> 
	;; Probe: C  = ?
	;; Probe: F  = ?=> done
	;; 19:user> 
	;; Probe: F  = 212
	;; Probe: C  = 100=> done