-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathexa3.3.5-make-connector.scm
203 lines (186 loc) · 7.08 KB
/
exa3.3.5-make-connector.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
;连接器的表示
;value是局部状态变量,informant是设置连接器值的对象,constraints是这一连接器涉及的所有约束的表
(define (make-connector)
(let ((value #f) (informant #f) (constraints '()))
(define (set-my-value newval setter)
(cond ((not (has-value? me))
(set! value newval)
(set! informant setter)
(for-each-except setter
inform-about-value
constraints))
((not (= value newval))
(error "Contradiction" (list value newval)))
(else 'ignored)))
(define (forget-my-value retractor)
(if (eq? retractor informant)
(begin (set! informant #f)
(for-each-except retractor
inform-about-no-value
constraints))
'ignored))
(define (connect new-constraint)
(if (not (memq new-constraint constraints))
(set! constraints
(cons new-constraint constraints)))
(if (has-value? me)
(inform-about-value new-constraint))
'done)
(define (me request)
(cond ((eq? request 'has-value?)
(if informant #t #f))
((eq? request 'value) value)
((eq? request 'set-value!) set-my-value)
((eq? request 'forget) forget-my-value)
((eq? request 'connect) connect)
(else (error "Unknown operation -- CONNECTOR" request))))
me))
;将一个指定的过程应用于一个表中除了给定的特例之外的所有对象
(define (for-each-except exception procedure list)
(define (loop items)
(cond ((null? items) 'done)
((eq? (car items) exception) (loop (cdr items)))
(else (procedure (car items))
(loop (cdr items)))))
(loop list))
;连接器是否有值
(define (has-value? connector)
(connector 'has-value?))
;返回连接器的值
(define (get-value connector)
(connector 'value))
;信息源(informant)连接器的值设置为新值
(define (set-value! connector new-value informant)
((connector 'set-value!) new-value informant))
;撤销源(retractor)要求连接器忘记其值
(define (forget-value! connector retractor)
((connector 'forget) retractor))
;通知连接器参与一个新约束
(define (connect connector new-constraint)
((connector 'connect) new-constraint))
;与各个相关约束通信,告知给定的约束,现在该连接器有了一个新值
(define (inform-about-value constraint)
(constraint 'I-have-a-value))
;告知相关约束,该连接器丧失了自己原有的值
(define (inform-about-no-value constraint)
(constraint 'I-lost-my-value))
;在被求和连接器a1和a2与和连接器sum之间构造出一个加法约束
(define (adder a1 a2 sum)
(define (process-new-value)
(cond ((and (has-value? a1) (has-value? a2))
(set-value! sum
(+ (get-value a1) (get-value a2))
me))
((and (has-value? a1) (has-value? sum))
(set-value! a2
(- (get-value sum) (get-value a1))
me))
((and (has-value? a2) (has-value? sum))
(set-value! a1
(- (get-value sum) (get-value a2))
me))))
(define (process-forget-value)
(forget-value! sum me)
(forget-value! a1 me)
(forget-value! a2 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 -- ADDER" request))))
(connect a1 me)
(connect a2 me)
(connect sum me)
me)
;乘法约束
(define (multiplier m1 m2 product)
(define (process-new-value)
(cond ((or (and (has-value? m1) (= (get-value m1) 0))
(and (has-value? m2) (= (get-value m2) 0)))
(set-value! product 0 me))
((and (has-value? m1) (has-value? m2))
(set-value! product
(* (get-value m1) (get-value m2))
me))
((and (has-value? product) (has-value? m1))
(set-value! m2
(/ (get-value product) (get-value m1))
me))
((and (has-value? product) (has-value? m2))
(set-value! m1
(/ (get-value product) (get-value m2))
me))))
(define (process-forget-value)
(forget-value! product me)
(forget-value! m1 me)
(forget-value! m2 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 -- MULTIPLIER" request))))
(connect m1 me)
(connect m2 me)
(connect product me)
me)
;常量约束,让连接器成为一个常量,不允许更改
(define (constant value connector)
(define (me request)
(error "Unkonwn request -- CONSTANT" request))
(connect connector me)
(set-value! connector value me)
me)
;监视器,在指定连接器被设置或取消值的时候打印一个消息
(define (probe name connector)
(define (print-probe value)
(newline)
(display "Probe: ")
(display name)
(display " = ")
(display value))
(define (process-new-value)
(print-probe (get-value connector)))
(define (process-forget-value)
(print-probe "?"))
(define (me request)
(cond ((eq? request 'I-have-a-value)
(process-new-value))
((eq? request 'I-lost-my-value)
(process-forget-value))
(else
(error "Unkonwn request -- PROBE" request))))
(connect connector me)
me)
;---------------------------------------------------------------
;约束系统的使用
;一个华氏温度和摄氏温度的约束网络
(define (celsius-fahrenheit-converter c f)
(let ((u (make-connector))
(v (make-connector))
(w (make-connector))
(x (make-connector))
(y (make-connector)))
(multiplier c w u)
(multiplier v x u)
(adder v y f)
(constant 9 w)
(constant 5 x)
(constant 32 y)
'ok))
;测试
;(define C (make-connector))
;(define F (make-connector))
;(celsius-fahrenheit-converter C F)
;安装监视器
;(probe "Celsius temp" C)
;(probe "Fahrenheit temp" F)
;(set-value! C 25 'user)
;(set-value! F 212 'user) ;==> Exception in error: invalid message argument (77 212)
;(forget-value! C 'user)
;(set-value! F 212 'user)