3.3.5 Propagation of Constraints

等式を制約として扱うことで解を求める。項どうしが演算、等号で結合されていればそれはそれらの項に対する制約と見なせる。たとえば a + b = c という式なら、どの2変数が決まっても残り1つの変数は自動的に決まる。これを自動化することを考えてる。おもしろい。
前の節の回路のモデルのように項どうしを接続して、ある項の値が具体的が決まったときに接続された項に対して通知を行ない、さらにその項から制約を伝播させることを繰り返して、式全体の値を決定することができる(かもしれない)。
全部のコード載せたら見通しが悪いので、テキストに無い分だけ載せることにする。

3.33

部品を組み合わせて、(a + b) / 2 = c の形の制約を作る。

(define (averager a b c)
  (let ((a+b (make-connector))
        (two (make-connector)))
    (adder a b a+b)
    (constant 2 two)
    (multiplier c two a+b)))

3.34

以下が上手くいかないのはなぜか?

; a^2 = b
(define (squarer a b)
  (multiplier a a b))

bだけに制約が与えられたとき、残りの1つ(aの値)が決まると期待するけど、内部では a * a = b という形になっていて制約が一つ足りないから。

3.35 (うまくいくsquarerを作る)

(define (squarer a b)
  (define (process-new-value)
    (if (has-value? b)
      (if (< (get-value b) 0)
        (error "square less than 0 -- SQUARER" (get-value b))
        (set-value! a (sqrt (b 'value)) me))
      (if (has-value? a)
        (set-value! b (* (a 'value) (a 'value)) me)
        'ignored)))
  (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)

3.36 (connectorを内部に隠す)

以下のコードでうまくいくようにする。

(define (celsius-fahrenheit-converter x)
  (c+ (c* (c/ (cv 9) (cv 5))
          x)
      (cv 32)))
(define C (make-connector))
(define F (celsius-fahrenheit-converter C))
(define (c+ x y)
  (let ((z (make-connector)))
    (adder x y z)
    z))

(define (c* x y)
  (let ((z (make-connector)))
    (multiplier x y z)
    z))

(define (c/ x y)
  (let ((z (make-connector)))
    (multiplier y z x)
    z))

(define (cv v)
  (let ((x (make-connector)))
    (constant v x)
    x))