diff --git a/ex-4_78-79.scm b/ex-4_78-79.scm index 6e233ce..48200df 100644 --- a/ex-4_78-79.scm +++ b/ex-4_78-79.scm @@ -34,14 +34,14 @@ (newline) (display output-prompt) ;; [extra newline at end] (announce-output output-prompt) - (display-stream - (stream-map + (display-list + (map (lambda (frame) (instantiate q frame (lambda (v f) (contract-question-mark v)))) - (qeval q (singleton-stream '())))) + (qeval q (singleton-list '())))) (query-driver-loop))))) (define (instantiate exp frame unbound-var-handler) @@ -60,69 +60,69 @@ ;;;SECTION 4.4.4.2 ;;;The Evaluator -(define (qeval query frame-stream) +(define (qeval query frame-list) + ;; (display "QEVAL ") (display query) (newline) (let ((qproc (get (type query) 'qeval))) (if qproc - (qproc (contents query) frame-stream) - (simple-query query frame-stream)))) + (qproc (contents query) frame-list) + (simple-query query frame-list)))) ;;;Simple queries -(define (simple-query query-pattern frame-stream) +(define (simple-query query-pattern frame-list) ;; (display "SIMPLE-QUERY ") (display query-pattern) (newline) - (stream-flatmap + (flatmap (lambda (frame) - (stream-append-delayed + (append (find-assertions query-pattern frame) - (delay (apply-rules query-pattern frame)))) - frame-stream)) + (apply-rules query-pattern frame))) + frame-list)) ;;;Compound queries -(define (conjoin conjuncts frame-stream) +(define (conjoin conjuncts frame-list) (if (empty-conjunction? conjuncts) - frame-stream + frame-list (conjoin (rest-conjuncts conjuncts) (qeval (first-conjunct conjuncts) - frame-stream)))) + frame-list)))) ;;(put 'and 'qeval conjoin) -(define (disjoin disjuncts frame-stream) +(define (disjoin disjuncts frame-list) (if (empty-disjunction? disjuncts) - the-empty-stream - (interleave-delayed - (qeval (first-disjunct disjuncts) frame-stream) - (delay (disjoin (rest-disjuncts disjuncts) - frame-stream))))) + '() + (interleave + (qeval (first-disjunct disjuncts) '()) + (disjoin (rest-disjuncts disjuncts) frame-list)))) ;;(put 'or 'qeval disjoin) ;;;Filters -(define (negate operands frame-stream) - (stream-flatmap +(define (negate operands frame-list) + (flatmap (lambda (frame) - (if (stream-null? (qeval (negated-query operands) - (singleton-stream frame))) - (singleton-stream frame) - the-empty-stream)) - frame-stream)) + (if (null? (qeval (negated-query operands) + (singleton-list frame))) + (singleton-list frame) + '())) + frame-list)) -(define (uniquely-asserted query frame-stream) - (stream-flatmap +(define (uniquely-asserted query frame-list) + (flatmap (lambda (frame) - (let ((matches (qeval (car query) (singleton-stream frame)))) - (cond ((stream-null? matches) matches) - ((stream-null? (stream-cdr matches)) matches) - (else the-empty-stream)))) - frame-stream)) + (let ((matches (qeval (car query) (singleton-list frame)))) + (cond ((null? matches) matches) + ((null? (cdr matches)) matches) + (else '())))) + frame-list)) ;;(put 'not 'qeval negate) -(define (lisp-value call frame-stream) - (stream-flatmap +(define (lisp-value call frame-list) + (flatmap (lambda (frame) (if (execute (instantiate @@ -130,34 +130,33 @@ frame (lambda (v f) (error "Unknown pat var -- LISP-VALUE" v)))) - (singleton-stream frame) - the-empty-stream)) - frame-stream)) + (singleton-list frame) + '())) + frame-list)) ;;(put 'lisp-value 'qeval lisp-value) (define (execute exp) + (display "EXECUTE ") (display exp) (newline) (apply (eval (predicate exp) user-initial-environment) (args exp))) -(define (always-true ignore frame-stream) frame-stream) +(define (always-true ignore frame-list) frame-list) ;;(put 'always-true 'qeval always-true) -;;;SECTION 4.4.4.3 -;;;Finding Assertions by Pattern Matching - (define (find-assertions pattern frame) - (stream-flatmap (lambda (datum) - (check-an-assertion datum pattern frame)) - (fetch-assertions pattern frame))) + ;; (display "FIND-ASSERTIONS ") (display pattern) (newline) + (flatmap + (lambda (datum) (check-an-assertion datum pattern frame)) + (fetch-assertions pattern frame))) (define (check-an-assertion assertion query-pat query-frame) (let ((match-result (pattern-match query-pat assertion query-frame))) (if (eq? match-result 'failed) - the-empty-stream - (singleton-stream match-result)))) + '() + (singleton-list match-result)))) (define (pattern-match pat dat frame) (cond ((eq? frame 'failed) 'failed) @@ -181,9 +180,9 @@ ;;;Rules and Unification (define (apply-rules pattern frame) - (stream-flatmap (lambda (rule) - (apply-a-rule rule pattern frame)) - (fetch-rules pattern frame))) + (flatmap (lambda (rule) + (apply-a-rule rule pattern frame)) + (fetch-rules pattern frame))) (define (apply-a-rule rule query-pattern query-frame) (let ((clean-rule (rename-variables-in rule))) @@ -192,9 +191,9 @@ (conclusion clean-rule) query-frame))) (if (eq? unify-result 'failed) - the-empty-stream + '() (qeval (rule-body clean-rule) - (singleton-stream unify-result)))))) + (singleton-list unify-result)))))) (define (rename-variables-in rule) (let ((rule-application-id (new-rule-application-id))) @@ -253,9 +252,10 @@ ;;;SECTION 4.4.4.5 ;;;Maintaining the Data Base -(define THE-ASSERTIONS the-empty-stream) +(define THE-ASSERTIONS '()) (define (fetch-assertions pattern frame) + ;; (display "FETCH-ASSERTIONS ") (display pattern) (newline) (if (use-index? pattern) (get-indexed-assertions pattern) (get-all-assertions))) @@ -267,9 +267,9 @@ (define (get-stream key1 key2) (let ((s (get key1 key2))) - (if s s the-empty-stream))) + (if s s '()))) -(define THE-RULES the-empty-stream) +(define THE-RULES '()) (define (fetch-rules pattern frame) (if (use-index? pattern) @@ -279,7 +279,7 @@ (define (get-all-rules) THE-RULES) (define (get-indexed-rules pattern) - (stream-append + (append (get-stream (index-key-of pattern) 'rule-stream) (get-stream '? 'rule-stream))) @@ -292,13 +292,13 @@ (store-assertion-in-index assertion) (let ((old-assertions THE-ASSERTIONS)) (set! THE-ASSERTIONS - (cons-stream assertion old-assertions)) + (cons assertion old-assertions)) 'ok)) (define (add-rule! rule) (store-rule-in-index rule) (let ((old-rules THE-RULES)) - (set! THE-RULES (cons-stream rule old-rules)) + (set! THE-RULES (stream rule old-rules)) 'ok)) (define (store-assertion-in-index assertion) @@ -308,8 +308,8 @@ (get-stream key 'assertion-stream))) (put key 'assertion-stream - (cons-stream assertion - current-assertion-stream)))))) + (cons assertion + current-assertion-stream)))))) (define (store-rule-in-index rule) (let ((pattern (conclusion rule))) @@ -319,8 +319,8 @@ (get-stream key 'rule-stream))) (put key 'rule-stream - (cons-stream rule - current-rule-stream))))))) + (cons rule + current-rule-stream))))))) (define (indexable? pat) (or (constant-symbol? (car pat)) @@ -336,35 +336,34 @@ ;;;SECTION 4.4.4.6 ;;;Stream operations -(define (stream-append-delayed s1 delayed-s2) - (if (stream-null? s1) - (force delayed-s2) - (cons-stream - (stream-car s1) - (stream-append-delayed (stream-cdr s1) delayed-s2)))) +(define stream-null? null?) -(define (interleave-delayed s1 delayed-s2) - (if (stream-null? s1) - (force delayed-s2) - (cons-stream - (stream-car s1) - (interleave-delayed (force delayed-s2) - (delay (stream-cdr s1)))))) +(define (interleave s1 s2) + (if (null? s1) + s2 + (cons + (car s1) + (interleave s2 (cdr s1))))) -(define (stream-flatmap proc s) - (flatten-stream (stream-map proc s))) +(define (flatmap proc xs) + (flatten (map proc xs))) -(define (flatten-stream stream) - (if (stream-null? stream) - the-empty-stream - (interleave-delayed - (stream-car stream) - (delay (flatten-stream (stream-cdr stream)))))) +(define (map proc xs) + (if (null? xs) + '() + (cons (proc (car xs)) + (map proc (cdr xs))))) -(define (singleton-stream x) - (cons-stream x the-empty-stream)) +(define (flatten stream) + (if (null? stream) + '() + (interleave + (car stream) + (flatten (cdr stream))))) +(define (singleton-list x) + (cons x '())) ;;;SECTION 4.4.4.7 ;;;Query syntax procedures @@ -481,47 +480,14 @@ ;;;;Stream support from Chapter 3 +(define (display-list s) + (map display-line s)) -(define (stream-map proc s) - (if (stream-null? s) - the-empty-stream - (cons-stream (proc (stream-car s)) - (stream-map proc (stream-cdr s))))) - -(define (stream-for-each proc s) - (if (stream-null? s) - 'done - (begin (proc (stream-car s)) - (stream-for-each proc (stream-cdr s))))) - -(define (display-stream s) - (stream-for-each display-line s)) (define (display-line x) - (newline) - (display x)) - -(define (stream-filter pred stream) - (cond ((stream-null? stream) the-empty-stream) - ((pred (stream-car stream)) - (cons-stream (stream-car stream) - (stream-filter pred - (stream-cdr stream)))) - (else (stream-filter pred (stream-cdr stream))))) - -(define (stream-append s1 s2) - (if (stream-null? s1) - s2 - (cons-stream (stream-car s1) - (stream-append (stream-cdr s1) s2)))) - -(define (interleave s1 s2) - (if (stream-null? s1) - s2 - (cons-stream (stream-car s1) - (interleave s2 (stream-cdr s1))))) + (display x) + (newline)) ;;;;Table support from Chapter 3, Section 3.3.3 (local tables) - (define (make-table) (let ((local-table (list '*table*))) (define (lookup key-1 key-2) @@ -561,8 +527,8 @@ (define (initialize-data-base rules-and-assertions) (define (deal-out r-and-a rules assertions) (cond ((null? r-and-a) - (set! THE-ASSERTIONS (list->stream assertions)) - (set! THE-RULES (list->stream rules)) + (set! THE-ASSERTIONS assertions) + (set! THE-RULES rules) 'done) (else (let ((s (query-syntax-process (car r-and-a)))) @@ -694,8 +660,32 @@ )) +(define (rule-to-be-added? exp) + (eq? (car exp) 'rule)) + +(define (eval-query input) + (let ((q (query-syntax-process input))) + (cond ((assertion-to-be-added? q) + (add-rule-or-assertion! (add-assertion-body q))) + ((rule-to-be-added? q) + (add-rule-or-assertion! q)) + (else + (display-list + (map + (lambda (frame) + (instantiate q + frame + (lambda (v f) + (contract-question-mark v)))) + (qeval q (singleton-list '())))))))) + (initialize-data-base microshaft-data-base) +(eval-query + '(and (salary (Bitdiddle Ben) ?ben-amount) + (salary ?person ?amount) + (lisp-value > ?amount ?ben-amount))) + (display "[done]\n") )) @@ -705,15 +695,5 @@ ; evaluator. The next step is to implement analyze-or in the non-deterministic ; evaluator. -; Exercise 4.78. Redesign the query language as a nondeterministic program to -; be implemented using the evaluator of section 4.3, rather than as a stream -; process. In this approach, each query will produce a single answer (rather -; than the stream of all answers) and the user can type try-again to see more -; answers. You should find that much of the mechanism we built in this section -; is subsumed by nondeterministic search and backtracking. You will probably -; also find, however, that your new query language has subtle differences in -; behavior from the one implemented here. Can you find examples that illustrate -; this difference? - (display "\nex-4.79\n") diff --git a/misc/sicp-ambeval.scm b/misc/sicp-ambeval.scm index 20fbf4f..7b10064 100644 --- a/misc/sicp-ambeval.scm +++ b/misc/sicp-ambeval.scm @@ -394,21 +394,27 @@ ((if-fail? exp) (analyze-if-fail exp)) ((lambda? exp) (analyze-lambda exp)) ((begin? exp) (analyze-sequence (begin-actions exp))) + ((apply? exp) (analyze-apply (cdr exp))) ((cond? exp) (analyze (cond->if exp))) ((let? exp) (analyze (let->combination exp))) ;** ((amb? exp) (analyze-amb exp)) ;** ((ramb? exp) (analyze-ramb exp)) ;** ((lamb? exp) (analyze-lamb exp)) ;** - ((or? exp) (analyze-or exp)) + ((or? exp) (analyze-or (clauses exp))) + ((and? exp) (analyze-and (clauses exp))) ((application? exp) (analyze-application exp)) (else (error "Unknown expression type -- ANALYZE" exp)))) +(define (apply? exp) (tagged-list? exp 'apply)) +(define (analyze-apply exp) + (display "ANALYZE-APPLY ") (newline) + (display exp) + (lambda (env succeed fail) (succeed #t fail))) + (define (ambeval exp env succeed fail) ((analyze exp) env succeed fail)) -;;;Simple expressions - (define (analyze-self-evaluating exp) (lambda (env succeed fail) (succeed exp fail))) @@ -431,11 +437,39 @@ fail)))) (define (or? exp) (tagged-list? exp 'or)) +(define (and? exp) (tagged-list? exp 'and)) (define (clauses exp) (cdr exp)) (define (no-clauses? exp) (null? exp)) (define (first-clause exp) (car exp)) (define (rest-clauses exp) (cdr exp)) -; TODO: (define (analyze-or exp) ...) + +(define (analyze-or exp) + (if (no-clauses? exp) + (lambda (env succeed fail) (succeed #f fail)) + (let ((cproc (analyze (first-clause exp)))) + (lambda (env succeed fail) + (cproc + env + ;; success continuation for clause value + (lambda (clause-value fail2) + (if (true? clause-value) + (succeed #t fail2) + ((analyze-or (rest-clauses exp)) env succeed fail2))) + fail))))) + +(define (analyze-and exp) + (if (no-clauses? exp) + (lambda (env succeed fail) (succeed #t fail)) + (let ((cproc (analyze (first-clause exp)))) + (lambda (env succeed fail) + (cproc + env + ;; success continuation for clause value + (lambda (clause-value fail2) + (if (true? clause-value) + ((analyze-and (rest-clauses exp)) env succeed fail2) + (succeed #f fail2))) + fail))))) ;;;Conditionals and sequences (define (analyze-if exp) @@ -647,10 +681,13 @@ (list '>= >=) (list 'abs abs) (list 'assoc assoc) + (list 'append append) + (list 'cadr cadr) (list 'car car) (list 'cdr cdr) (list 'cons cons) (list 'display display) + (list 'equal? equal?) (list 'eq? eq?) (list 'integer? integer?) (list 'list list) @@ -664,11 +701,12 @@ (list 'set-car! set-car!) (list 'set-cdr! set-cdr!) (list 'sqrt sqrt) + (list 'string->symbol string->symbol) + (list 'string-length string-length) (list 'string=? string=?) (list 'substring substring) (list 'symbol->string symbol->string) (list 'symbol? symbol?) - (list 'the-empty-stream the-empty-stream) )) 'AMB-EVALUATOR-LOADED