-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexercise-4.4.scm
111 lines (104 loc) · 3.87 KB
/
exercise-4.4.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
;; Exercise 4.4
;; Exercise 4.4
;; Installed as new special forms
(define (and-package install-proc eval)
;; Internal definitions
(define (preds exp) (cdr exp))
(define (first-pred and-exps) (car and-exps))
(define (rest-preds and-exps) (cdr and-exps))
(define (last-pred? and-exps) (null? (cdr and-exps)))
(define (eval-and and-exps env)
(if (null? and-exps)
'true
(let ((first-value (eval (first-pred and-exps) env)))
(cond ((last-pred? and-exps) first-value)
((true? first-value)
(eval-and (rest-preds and-exps) env))
(else 'false)))))
;; Interface
(install-proc
(list
(list 'eval 'and (lambda (exp env) (eval-and (preds exp) env)))))
'and-package-installed!)
(define (or-package install-proc eval)
;; Internal definitions
(define (preds exp) (cdr exp))
(define (first-pred or-exps) (car or-exps))
(define (rest-preds or-exps) (cdr or-exps))
(define (last-pred? or-exps) (null? (cdr or-exps)))
(define (eval-or or-exps env)
(if (null? or-exps)
'false
(let ((first-value (eval (first-pred or-exps) env)))
(cond ((true? first-value) 'true)
(else (eval-or (rest-preds or-exps) env))))))
;; Interface
(install-proc
(list
(list 'eval 'or (lambda (exp env) (eval-or (preds exp) env)))))
'or-package-installed!)
(and-package table-installer eval)
(or-package table-installer eval)
;; Installed as derived expressions
(define (and-package install-proc eval)
(define (make-if pred cons alt)
(list 'if pred cons alt))
(define (eval-and exps env)
(cond ((null? exps) 'true)
((null? (cdr exps))
(eval (make-if (car exps) (car exps) 'false) env))
(else (eval (make-if (car exps) (cons 'and (cdr exps)) 'false) env))))
(install-proc
(list
(list 'eval 'and (lambda (exp env) (eval-and (cdr exps) env)))))
'and-package-installed!)
(define (or-package install-proc eval)
(define (make-if pred cons alt)
(list 'if pred cons alt))
(define (eval-or exps env)
(if (null? exps)
'false
(eval (make-if (car exps) (car exps) (cons 'or (cdr exps))) env)))
(install-proc
(list
(list 'eval 'or (lambda (exp env) (eval-or (cdr exps) env)))))
'or-package-installed!)
;; Installed as top level forms to eval
(define (eval exp env)
(cond ((self-evaluating? exp) exp)
((variable? exp) (lookup-variable-value exp env))
((quoted? exp) (text-of-quotation exp))
((assignment? exp) (eval-assignment exp env))
((definition? exp) (eval-definition exp env))
((if? exp) (eval-if exp env))
((lambda? exp)
(make-procedure (lambda-parameters exp)
(lambda-body exp)
env))
((begin? exp)
(eval-sequence (begin-actions exp) env))
((and? exp) (eval (and->if (and-predicates exp)) env))
((or? exp) (eval (or->if (or-predicates exp) env)))
((cond? exp) (eval (cond->if exp) env))
((application? exp)
(apply (eval (operator exp) env)
(list-of-values (operands exp) env)))
(else (error "Unknown expression type: EVAL" exp))))
(define (and? exp) (tagged-list? exp 'and))
(define (and-predicates exp) (cdr exp))
(define (first-pred preds) (car preds))
(define (rest-preds preds) (cdr preds))
(define (last-pred? preds) (null? (cadr preds)))
(define (and->if preds)
(cond ((null? preds) 'true)
((last-pred? preds) (first-pred preds))
(else (make-if (first-pred preds)
(and->if (rest-preds preds))
'false))))
(define (or? exp) (tagged-list? exp 'or))
(define (or-predicates exp) (cdr exp))
(define (or->if preds)
(cond ((null? preds) 'false)
(else (make-if (first-pred preds)
(first-pred preds)
(or->if (rest-preds preds))))))