SICP 読み (120) 3.3.5 制約の拡散

昨晩のエントリにて informant 云々について書いていますが、やっぱ読めていなかった。イケマセン。
制約同士がコネクタで繋っているケイスもある訳で (例示されているソレもそのパターンになっております)、逆に言えば関わりの無い制約に勝手に値を変更されては困りますな。
あと、例示されているソレは制約に関わっているコネクタは 3 つになっています。項が二つの式が前提になっているんですが、こんな式

(+ 1 2 3 4 5)

も実装可能、という事になるのではないかと。ただ、手続きの修正は必要。

問題 3.34

これは第一感のみ。

(define (squarer a b)
  (multiplier a a b))

って a が値を持っていない場合、計算できんと思う。
# ちなみに試験を作って確認すれば、なんですが略。

問題 3.35

できれば connector の試験も検討したいんですがどうなるか。とりあえず squarer の試験のみを以下に。

  ("3.35"
   ("squarer (1)"
    (let ((a (make-connector))
	  (b (make-connector)))
      (squarer a b)
      (assert-false (get-value a))
      (assert-false (get-value b))
      (set-value! a 10 'user)
      (assert-equal 100 (get-value b))
      )
    )
   
   ("squarer (2)"
    (let ((a (make-connector))
	  (b (make-connector)))
      (squarer a b)
      (assert-false (get-value a))
      (assert-false (get-value b))
      (set-value! b 100 'user)
      (assert-equal 10.0 (get-value a))
      )
    )
   )

実装が以下。一応上記試験にはパス。

(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 (get-value b)) me))
	(set-value! b (* (get-value a) (get-value a)) me)))
  (define (process-forgot-value)
    (forgot-value! a me)
    (forgot-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-forgot-value))
	  (else
	   (error "Unknown request -- MULTIPLIER" request))))
  (connect a me)
  (connect b me)
  me)

上記試験では全ての分岐がチェックできてませんね。ってか、次あたりからハードル上がってくるんですが、きちんと試験でカバーできてない、というナニが微妙。

追記

全ての分岐を通すべく、無駄な努力 (??) をしてみるか。って微妙な現実トウヒが入ってしまってダメ。

   ("squarer (3) - b is minus"
    (let ((a (make-connector))
	  (b (make-connector)))
      (squarer a b)
      (assert-error (lambda () (set-value! b -1 'user)))
      )
    )

   ("squarer (4) - request invalid"
    (let ((a (make-connector))
	  (b (make-connector)))
      (assert-error (lambda () ((squarer a b) 'xxx)))
      )
    )

一応全部の分岐を通ってはいるのか。connector をやるリキがあれば以下に追記が続くはずですが、時間が時間だけに微妙。