計算機プログラムの構造と解釈 第二版 P174 問題3.35

squarerを基本制約として作ってみようという問題。


そんなに難しく考える必要はなくて、
p171のaddr、もしくは、p172のmultiplierを参考につくる。


まず考えるべきは<代替部1>だけど、これは根をセットする部分だ。
if式になっているからちょっとあせるが、よく見てaにset-value!する式を書いた。


次に<代替部2>ここに書くべきは、
bが値を持っていなくて、aが値を持っているケースだとおもうので
if式からつけたしつつ、あとはよく見て、bにset-value!する式を書けばいい。


<本体1>に関してはほぼ写しただけ。
aとbにforget-value!して忘れさせてやって、process-new-valueした。


<本体2>にいたっては、エラーメッセージを変えただけだ。


そんな感じでできた。
constraint.scmは
http://d.hatena.ne.jp/unlearned/20100606/1275873184
と同様。

#!/usr/local/bin/gosh
;; -*- coding: utf-8 -*-

(use ggc.debug.trace)
(use math.mt-random)

(load "./constraints.scm")

;;;
; 実行
;;;

(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))
      (if (has-value? a)
        (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 "input" a)
(probe "squarer" b)


;; main
(define (main args)

  (print "(set-value! a 5 'user)")
  (set-value! a 5 'user)
  (newline)
  (newline)

  (print "(forget-value! a 'user)")
  (forget-value! a 'user)
  (newline)
  (newline)

  (print "(set-value! b 100 'user)")
  (set-value! b 100 'user)
  (newline)
  (newline)


  0)


実行

(set-value! a 5 'user)

Probe: input = 5
Probe: squarer = 25

(forget-value! a 'user)

Probe: input = ?
Probe: squarer = ?

(set-value! b 100 'user)

Probe: squarer = 100
Probe: input = 10.0


できている。と思う。