-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path2-4-3-data-directed-programming.rkt
153 lines (119 loc) · 3.89 KB
/
2-4-3-data-directed-programming.rkt
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
#lang racket
(define (square x) (* x x))
(define (attach-tag type-tag contents)
(cons type-tag contents))
(define (type-tag datum)
(if (pair? datum)
(car datum)
(error "Bad tagged datum:
TYPE-TAG" datum)))
(define (contents datum)
(if (pair? datum)
(cdr datum)
(error "Bad tagged datum:
CONTENTS" datum)))
; Operations table
(define operations '())
(define (put op type-tags proc)
(set! operations (cons (list op type-tags proc) operations)))
(define (get op type-tags)
(define (find operations-table)
(let ([operation (car operations-table)]
[rest (cdr operations-table)])
(cond
[(and (equal? (car operation) op)
(equal? (cadr operation) type-tags))
(caddr operation)]
[(null? rest) (error "Operation not found: GET" op type-tags)]
[else (find rest)])))
(find operations))
; Rectangular package
; The procedures are installed with '() list to cater for procedures accepting
; multiple arguments.
; Therefore we treat the current procedures as '(rectangle),
; a list of a single argument of type rectangular.
; The constructors need only a single 'rectangular as
; a constructor constructs a single value of a single type.
(define (install-rectangular-package)
(define (real-part z) (car z))
(define (imag-part z) (cdr z))
(define (make-from-real-imag x y)
(cons x y))
(define (magnitude z)
(sqrt (+ (square (real-part z)) (square (imag-part z)))))
(define (angle z)
(atan (imag-part z) (real-part z)))
(define (make-from-mag-ang r a)
(cons (* r (cos a)) (* r (sin a))))
(define (tag z)
(attach-tag 'rectangular z))
(put 'real-part '(rectangular) real-part)
(put 'imag-part '(rectangular) imag-part)
(put 'magnitude '(rectangular) magnitude)
(put 'angle '(rectangular) angle)
(put 'make-from-real-imag 'rectangular
(lambda (x y) (tag (make-from-real-imag x y))))
(put 'make-from-mag-ang 'rectangular
(lambda (r a) (tag (make-from-mag-ang r a))))
'install-rectangular-package-done)
; Polar package
; Trigonometry is used to find real and imaginary parts.
(define (install-polar-package)
(define (magnitude z) (car z))
(define (angle z) (cdr z))
(define (make-from-mag-ang r a)
(cons r a))
(define (real-part z)
(* (magnitude z) (cos (angle z))))
(define (imag-part z)
(* (magnitude z) (sin (angle z))))
(define (make-from-real-imag x y)
(cons (sqrt (+ (square x) (square y))) (atan y x)))
(define (tag z)
(attach-tag 'polar z))
(put 'real-part '(polar) real-part)
(put 'imag-part '(polar) imag-part)
(put 'magnitude '(polar) magnitude)
(put 'angle '(polar) angle)
(put 'make-from-real-imag 'polar
(lambda (x y) (tag (make-from-real-imag x y))))
(put 'make-from-mag-ang 'polar
(lambda (r a) (tag (make-from-mag-ang r a))))
'install-polar-package-done)
; Apply generic procedure
; '. args' is used to specify the rest of
; the arguments as a list.
(define (apply-generic op . args)
(let ([type-tags (map type-tag args)])
(let ([proc (get op type-tags)])
(if proc
(apply proc (map contents args))
(error "No method for these types:
APPLY-GENERIC"
(list op type-tags))))))
; Generic Selectors
(define (real-part z)
(apply-generic 'real-part z))
(define (imag-part z)
(apply-generic 'imag-part z))
(define (magnitude z)
(apply-generic 'magnitude z))
(define (angle z)
(apply-generic 'angle z))
; Constructors
(define (make-from-real-imag x y)
((get 'make-from-real-imag 'rectangular) x y))
(define (make-from-mag-ang r a)
((get 'make-from-mag-ang 'polar) r a))
; Export procedures
(provide install-rectangular-package
install-polar-package
attach-tag
put
get
operations
real-part
imag-part
magnitude
angle
apply-generic)