2 (define (assoc key records)
3 (cond ((null? records) false)
4 ((equal? key (caar records)) (car records))
5 (else (assoc key (cdr records)))))
6 (let ((local-table (list '*table*)))
7 (define (lookup key-1 key-2)
8 (let ((subtable (assoc key-1 (cdr local-table))))
10 (let ((record (assoc key-2 (cdr subtable))))
15 (define (insert! key-1 key-2 value)
16 (let ((subtable (assoc key-1 (cdr local-table))))
18 (let ((record (assoc key-2 (cdr subtable))))
20 (set-cdr! record value)
22 (cons (cons key-2 value)
30 (cond ((eq? m 'lookup-proc) lookup)
31 ((eq? m 'insert-proc!) insert!)
32 (else (error "Unknown operation -- TABLE" m))))
35 (define operation-table (make-table))
36 (define get (operation-table 'lookup-proc))
37 (define put (operation-table 'insert-proc!))
39 (define (memo-proc proc)
40 (let ((already-run? false) (result false))
44 (begin (set! already-run? true)
48 (define-syntax mydelay
49 (rsc-macro-transformer
52 `(memo-proc (lambda () ,exp)))))
54 (apply xfmr (cdr e))))))
56 (define (myforce delayed-object)
59 (define-syntax cons-stream
60 (rsc-macro-transformer
61 (let ((xfmr (lambda (x y) `(cons ,x (mydelay ,y)))))
63 (apply xfmr (cdr e))))))
65 (define (stream-car s)
67 (define (stream-cdr s)
69 (define stream-null? null?)
70 (define the-empty-stream '())
71 (define (stream-map proc . argstreams)
72 (if (stream-null? (car argstreams))
75 (apply proc (map stream-car argstreams))
76 (apply stream-map (cons proc (map stream-cdr argstreams))))))
77 (define (display-stream s)
78 (stream-for-each display-line s))
79 (define (stream-for-each proc s)
82 (begin (proc (stream-car s))
83 (stream-for-each proc (stream-cdr s)))))
84 (define (display-line x)
88 (define (test-case actual expected)
93 (display "Expected: ")
96 (define (display-streams n . streams)
101 (display (stream-car s))
104 (apply display-streams
105 (cons (- n 1) (map stream-cdr streams))))))
106 (define (list->stream list)
109 (cons-stream (car list)
110 (list->stream (cdr list)))))
113 (define (eval-queries queries)
116 (begin (eval-query (car queries))
117 (eval-queries (cdr queries)))))
118 (define (eval-query query)
119 (let ((q (query-syntax-process query)))
120 (if (assertion-to-be-added? q)
121 (add-rule-or-assertion! (add-assertion-body q))
127 (contract-question-mark v))))
128 (qeval q (singleton-stream '()))))))
129 (define (eval-display-query q)
130 (display-stream (eval-query q)))
133 (define input-prompt ";;; Query input:")
134 (define output-prompt ";;; Query results:")
135 (define (query-driver-loop)
136 (prompt-for-input input-prompt)
137 (let ((q (query-syntax-process (read))))
138 (cond ((assertion-to-be-added? q)
139 (add-rule-or-assertion! (add-assertion-body q))
141 (display "Assertion added to data base.")
145 (display output-prompt)
152 (contract-question-mark v))))
153 (qeval q (singleton-stream '()))))
154 (query-driver-loop)))))
155 (define (instantiate exp frame unbound-var-handler)
158 (let ((binding (binding-in-frame exp frame)))
160 (copy (binding-value binding))
161 (unbound-var-handler exp frame))))
163 (cons (copy (car exp)) (copy (cdr exp))))
166 (define (qeval query frame-stream)
167 (let ((qproc (get (type query) 'qeval)))
169 (qproc (contents query) frame-stream)
170 (simple-query query frame-stream))))
171 (define (simple-query query-pattern frame-stream)
174 (stream-append-delayed
175 (find-assertions query-pattern frame)
176 (delay (apply-rules query-pattern frame))))
178 (define (conjoin conjuncts frame-stream)
179 (if (empty-conjunction? conjuncts)
181 (conjoin (rest-conjuncts conjuncts)
182 (qeval (first-conjunct conjuncts)
184 (put 'and 'qeval conjoin)
185 (define (disjoin disjuncts frame-stream)
186 (if (empty-disjunction? disjuncts)
189 (qeval (first-disjunct disjuncts) frame-stream)
190 (delay (disjoin (rest-disjuncts disjuncts)
192 (put 'or 'qeval disjoin)
193 (define (negate operands frame-stream)
196 (if (stream-null? (qeval (negated-query operands)
197 (singleton-stream frame)))
198 (singleton-stream frame)
201 (put 'not 'qeval negate)
202 (define (lisp-value call frame-stream)
210 (error "Unknown pat var -- LISP-VALUE" v))))
211 (singleton-stream frame)
214 (put 'lisp-value 'qeval lisp-value)
215 (define (execute exp)
216 (apply (eval (predicate exp) user-initial-environment)
218 (define (always-true ignore frame-stream) frame-stream)
219 (put 'always-true 'qeval always-true)
220 (define (find-assertions pattern frame)
221 (stream-flatmap (lambda (datum)
222 (check-an-assertion datum pattern frame))
223 (fetch-assertions pattern frame)))
224 (define (check-an-assertion assertion query-pat query-frame)
226 (pattern-match query-pat assertion query-frame)))
227 (if (eq? match-result 'failed)
229 (singleton-stream match-result))))
230 (define (pattern-match pat dat frame)
231 (cond ((eq? frame 'failed) 'failed)
232 ((equal? pat dat) frame)
233 ((var? pat) (extend-if-consistent pat dat frame))
234 ((and (pair? pat) (pair? dat))
235 (pattern-match (cdr pat)
237 (pattern-match (car pat)
241 (define (extend-if-consistent var dat frame)
242 (let ((binding (binding-in-frame var frame)))
244 (pattern-match (binding-value binding) dat frame)
245 (extend var dat frame))))
246 (define (apply-rules pattern frame)
247 (stream-flatmap (lambda (rule)
248 (apply-a-rule rule pattern frame))
249 (fetch-rules pattern frame)))
250 (define (apply-a-rule rule query-pattern query-frame)
251 (let ((clean-rule (rename-variables-in rule)))
253 (unify-match query-pattern
254 (conclusion clean-rule)
256 (if (eq? unify-result 'failed)
258 (qeval (rule-body clean-rule)
259 (singleton-stream unify-result))))))
260 (define (rename-variables-in rule)
261 (let ((rule-application-id (new-rule-application-id)))
262 (define (tree-walk exp)
264 (make-new-variable exp rule-application-id))
266 (cons (tree-walk (car exp))
267 (tree-walk (cdr exp))))
270 (define (unify-match p1 p2 frame)
271 (cond ((eq? frame 'failed) 'failed)
272 ((equal? p1 p2) frame)
273 ((var? p1) (extend-if-possible p1 p2 frame))
274 ((var? p2) (extend-if-possible p2 p1 frame)) ; ***
275 ((and (pair? p1) (pair? p2))
276 (unify-match (cdr p1)
278 (unify-match (car p1)
282 (define (extend-if-possible var val frame)
283 (let ((binding (binding-in-frame var frame)))
286 (binding-value binding) val frame))
288 (let ((binding (binding-in-frame val frame)))
291 var (binding-value binding) frame)
292 (extend var val frame))))
293 ((depends-on? val var frame) ; ***
295 (else (extend var val frame)))))
296 (define (depends-on? exp var frame)
297 (define (tree-walk e)
301 (let ((b (binding-in-frame e frame)))
303 (tree-walk (binding-value b))
306 (or (tree-walk (car e))
307 (tree-walk (cdr e))))
310 (define THE-ASSERTIONS the-empty-stream)
311 (define (fetch-assertions pattern frame)
312 (if (use-index? pattern)
313 (get-indexed-assertions pattern)
314 (get-all-assertions)))
315 (define (get-all-assertions) THE-ASSERTIONS)
316 (define (get-indexed-assertions pattern)
317 (get-stream (index-key-of pattern) 'assertion-stream))
318 (define (get-stream key1 key2)
319 (let ((s (get key1 key2)))
320 (if s s the-empty-stream)))
321 (define THE-RULES the-empty-stream)
322 (define (fetch-rules pattern frame)
323 (if (use-index? pattern)
324 (get-indexed-rules pattern)
326 (define (get-all-rules) THE-RULES)
327 (define (get-indexed-rules pattern)
329 (get-stream (index-key-of pattern) 'rule-stream)
330 (get-stream '? 'rule-stream)))
331 (define (add-rule-or-assertion! assertion)
332 (if (rule? assertion)
333 (add-rule! assertion)
334 (add-assertion! assertion)))
335 (define (add-assertion! assertion)
336 (store-assertion-in-index assertion)
337 (let ((old-assertions THE-ASSERTIONS))
339 (cons-stream assertion old-assertions))
341 (define (add-rule! rule)
342 (store-rule-in-index rule)
343 (let ((old-rules THE-RULES))
344 (set! THE-RULES (cons-stream rule old-rules))
346 (define (store-assertion-in-index assertion)
347 (if (indexable? assertion)
348 (let ((key (index-key-of assertion)))
349 (let ((current-assertion-stream
350 (get-stream key 'assertion-stream)))
353 (cons-stream assertion
354 current-assertion-stream))))))
355 (define (store-rule-in-index rule)
356 (let ((pattern (conclusion rule)))
357 (if (indexable? pattern)
358 (let ((key (index-key-of pattern)))
359 (let ((current-rule-stream
360 (get-stream key 'rule-stream)))
364 current-rule-stream)))))))
365 (define (indexable? pat)
366 (or (constant-symbol? (car pat))
368 (define (index-key-of pat)
369 (let ((key (car pat)))
370 (if (var? key) '? key)))
371 (define (use-index? pat)
372 (constant-symbol? (car pat)))
373 (define (stream-append-delayed s1 delayed-s2)
374 (if (stream-null? s1)
378 (stream-append-delayed (stream-cdr s1) delayed-s2))))
379 (define (interleave-delayed s1 delayed-s2)
380 (if (stream-null? s1)
384 (interleave-delayed (force delayed-s2)
385 (delay (stream-cdr s1))))))
386 (define (stream-flatmap proc s)
387 (flatten-stream (stream-map proc s)))
388 (define (flatten-stream stream)
389 (if (stream-null? stream)
393 (delay (flatten-stream (stream-cdr stream))))))
394 (define (singleton-stream x)
395 (cons-stream x the-empty-stream))
399 (error "Unknown expression TYPE" exp)))
400 (define (contents exp)
403 (error "Unknown expression CONTENTS" exp)))
404 (define (assertion-to-be-added? exp)
405 (eq? (type exp) 'assert!))
406 (define (add-assertion-body exp)
407 (car (contents exp)))
408 (define (empty-conjunction? exps) (null? exps))
409 (define (first-conjunct exps) (car exps))
410 (define (rest-conjuncts exps) (cdr exps))
411 (define (empty-disjunction? exps) (null? exps))
412 (define (first-disjunct exps) (car exps))
413 (define (rest-disjuncts exps) (cdr exps))
414 (define (negated-query exps) (car exps))
415 (define (predicate exps) (car exps))
416 (define (args exps) (cdr exps))
417 (define (rule? statement)
418 (tagged-list? statement 'rule))
419 (define (conclusion rule) (cadr rule))
420 (define (rule-body rule)
421 (if (null? (cddr rule))
424 (define (query-syntax-process exp)
425 (map-over-symbols expand-question-mark exp))
426 (define (map-over-symbols proc exp)
428 (cons (map-over-symbols proc (car exp))
429 (map-over-symbols proc (cdr exp))))
430 ((symbol? exp) (proc exp))
432 (define (expand-question-mark symbol)
433 (let ((chars (symbol->string symbol)))
434 (if (string=? (substring chars 0 1) "?")
437 (substring chars 1 (string-length chars))))
440 (tagged-list? exp '?))
441 (define (constant-symbol? exp) (symbol? exp))
442 (define rule-counter 0)
443 (define (new-rule-application-id)
444 (set! rule-counter (+ 1 rule-counter))
446 (define (make-new-variable var rule-application-id)
447 (cons '? (cons rule-application-id (cdr var))))
448 (define (contract-question-mark variable)
451 (if (number? (cadr variable))
452 (string-append (symbol->string (caddr variable))
454 (number->string (cadr variable)))
455 (symbol->string (cadr variable))))))
456 (define (make-binding variable value)
457 (cons variable value))
458 (define (binding-variable binding)
460 (define (binding-value binding)
462 (define (binding-in-frame variable frame)
463 (assoc variable frame))
464 (define (extend variable value frame)
465 (cons (make-binding variable value) frame))
466 (define (tagged-list? exp tag)
467 (and (pair? exp) (eq? (car exp) tag)))
470 '((assert! (address (Bitdiddle Ben) (Slumerville (Ridge Road) 10)))
471 (assert! (job (Bitdiddle Ben) (computer wizard)))
472 (assert! (salary (Bitdiddle Ben) 60000))
473 (assert! (address (Hacker Alyssa P) (Cambridge (Mass Ave) 78)))
474 (assert! (job (Hacker Alyssa P) (computer programmer)))
475 (assert! (salary (Hacker Alyssa P) 40000))
476 (assert! (supervisor (Hacker Alyssa P) (Bitdiddle Ben)))
477 (assert! (address (Fect Cy D) (Cambridge (Ames Street) 3)))
478 (assert! (job (Fect Cy D) (computer programmer)))
479 (assert! (salary (Fect Cy D) 35000))
480 (assert! (supervisor (Fect Cy D) (Bitdiddle Ben)))
481 (assert! (address (Tweakit Lem E) (Boston (Bay State Road) 22)))
482 (assert! (job (Tweakit Lem E) (computer technician)))
483 (assert! (salary (Tweakit Lem E) 25000))
484 (assert! (supervisor (Tweakit Lem E) (Bitdiddle Ben)))
485 (assert! (address (Reasoner Louis) (Slumerville (Pine Tree Road) 80)))
486 (assert! (job (Reasoner Louis) (computer programmer trainee)))
487 (assert! (salary (Reasoner Louis) 30000))
488 (assert! (supervisor (Reasoner Louis) (Hacker Alyssa P)))
489 (assert! (supervisor (Bitdiddle Ben) (Warbucks Oliver)))
490 (assert! (address (Warbucks Oliver) (Swellesley (Top Heap Road))))
491 (assert! (job (Warbucks Oliver) (administration big wheel)))
492 (assert! (salary (Warbucks Oliver) 150000))
493 (assert! (address (Scrooge Eben) (Weston (Shady Lane) 10)))
494 (assert! (job (Scrooge Eben) (accounting chief accountant)))
495 (assert! (salary (Scrooge Eben) 75000))
496 (assert! (supervisor (Scrooge Eben) (Warbucks Oliver)))
497 (assert! (address (Cratchet Robert) (Allston (N Harvard Street) 16)))
498 (assert! (job (Cratchet Robert) (accounting scrivener)))
499 (assert! (salary (Cratchet Robert) 18000))
500 (assert! (supervisor (Cratchet Robert) (Scrooge Eben)))
501 (assert! (address (Aull DeWitt) (Slumerville (Onion Square) 5)))
502 (assert! (job (Aull DeWitt) (administration secretary)))
503 (assert! (salary (Aull DeWitt) 25000))
504 (assert! (supervisor (Aull DeWitt) (Warbucks Oliver)))
505 (assert! (can-do-job (computer wizard) (computer programmer)))
506 (assert! (can-do-job (computer wizard) (computer technician)))
507 (assert! (can-do-job (computer programmer)
508 (computer programmer trainee)))
509 (assert! (can-do-job (administration secretary)
510 (administration big wheel)))))
512 ;; Exercise 4.55. Give simple queries that retrieve the following information from the data base:
514 ;; a. all people supervised by Ben Bitdiddle;
516 (eval-display-query '(supervisor ?employee (Bitdiddle Ben)))
518 ;;b. the names and jobs of all people in the accounting division;
520 (eval-display-query '(job ?x (accounting . ?title)))
522 ;;c. the names and addresses of all people who live in Slumerville.
524 (eval-display-query '(address ?person (Slumerville . ?rest)))