関数型言語の勉強にSICPを読もう - (43) 3章 - 標準部品化力、オブジェクトおよび状態 (167-175ページ)

3.3.5 制約の拡散

制約の拡散のポイントは以下の通り。
登場人物は2人
コネクタと制約(constraint)
コネクタは1つ以上の制約をリストとして持っている(1つ以上の制約と接続されている)

制約は自分が接続しているコネクタの値が変更したときに呼ばれる手続きを定義しておく。
その手続きを呼ぶと制約が接続しているコネクタの値が変わるかもしれない。

コネクタは自分自身の値が set-value! で変更されると接続している上で説明した制約の手続きを呼ぶ。
その手続きで他のコネクタの値が変更されれば、値の変更が伝播していくという仕組み。

問題3.33

(load "./3.3.5.scm")

(define (averager a b c)
  (let ((s (make-connector))
        (t (make-connector)))
    (adder a b s)
    (constant 0.5 t)
    (multiplier s t c)
    'ok))

;; test
(define A (make-connector))
(define B (make-connector))
(define AVERAGE (make-connector))

(averager A B AVERAGE)

(probe 'a A)
(probe 'b B)
(probe 'average AVERAGE)

(set-value! A 99 'user)
(set-value! B 1 'user)

結果

colinux% gosh 3.33.scm
Probe: a = 99
Probe: b = 1
Probe: average = 50.0

問題3.34

これは以下のようにやってみるとすぐ分かる

(load "./3.3.5.scm")

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

;; test
(define A (make-connector))
(define B (make-connector))

(squarer A B)

(probe 'a A)
(probe 'b B)

(set-value! B 169 'user)


squarerであれば、169という結果が与えられれば a = 13という答えを返すことを期待される。
しかし実装が multiplierを使っているのでこれではうまくいない。

問題3.35

(load "./3.3.5.scm")

(define (squarer a b)
  (define (process-new-value)
    (if (has-value? b)
        (if (< (get-value b) 0)
            (error "square less than 0")
            (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))
  (define (me request)
    (cond ((eq? request 'I-have-a-value)
           (process-new-value))
          ((eq? request 'I-lost-my-value)
           (process-forget-value))
          (else
           (error "unknow request"))))
  (connect a me)
  (connect b me)
  me)

;; test
(define A (make-connector))
(define B (make-connector))

(squarer A B)

(probe 'a A)
(probe 'b B)

(set-value! A 12 'user)

;;(set-value! B 169 'user)

3.36,3.37


※「SICPを読もう」の目次はこちら

計算機プログラムの構造と解釈
Gerald Jay Sussman Julie Sussman Harold Abelson 和田 英一
ピアソンエデュケーション (2000/02)
売り上げランキング: 56,404