根据公式 \(x^2 = y\) 和 \(\sqrt{y} = x\) ,只要知道 \(x\) 和 \(y\) 中的任意一个,就可以求出另外一个。
以下是 squarer
的定义:
;;; 35-squarer.scm
(load "p205-constraint.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
(square (get-value a))
me)
(error "Neither a nor b has value"))))
(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 "Unknown request -- MULTIPLIER" request))))
(connect a me)
(connect b me)
me)
注意, squarer
约束和书本给出的 adder
和 multiplier
约束都不同的地方是, squarer
只有两个连接器输入,因此在 process-forget-value
的最后,不必再调用 (process-new-value)
,否则就会出错(这肯定是作者设置的一个陷阱)。
测试:
1 ]=> (load "35-squarer.scm")
;Loading "35-squarer.scm"...
; Loading "p205-constraint.scm"...
; Loading "p201-constraint-interface.scm"... done
; Loading "p201-adder.scm"... done
; Loading "p202-multiplier.scm"... done
; Loading "p202-constant.scm"... done
; Loading "p203-probe.scm"... done
; Loading "p203-make-connector.scm"... done
; ... done
;... done
;Value: squarer
1 ]=> (define a (make-connector))
;Value: a
1 ]=> (define b (make-connector))
;Value: b
1 ]=> (probe "a" a)
;Value 11: #[compound-procedure 11 me]
1 ]=> (probe "b" b)
;Value 12: #[compound-procedure 12 me]
1 ]=> (squarer a b)
;Value 13: #[compound-procedure 13 me]
1 ]=> (set-value! a 3 'user)
Probe: b = 9
Probe: a = 3
;Value: done
1 ]=> (forget-value! a 'user)
Probe: b = ?
Probe: a = ?
;Value: done
1 ]=> (set-value! b 16 'user)
Probe: a = 4
Probe: b = 16
;Value: done