summaryrefslogtreecommitdiff
path: root/coding-exercises/2/74.rkt
blob: c6bc13711963a3b055127f3b5160e8f4c2998a38 (plain)
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
#lang racket
(require "../../shared/data-directed-programming.rkt")
(require "../../shared/lists.rkt")

(define test-dispatch (make-dispatch-table))
(define get (getter test-dispatch))
(define put (putter test-dispatch))

;; Example implementations
(define test-division (attach-tag 
                          'division-a
                          (list (attach-tag 
                                  'henk 
                                  (list (attach-tag 'salary 100))))))
(put 'record 'division-a (lambda (file-set employee) 
                           (let ((record (find-first 
                                           (make-eq-type? employee) 
                                           file-set)))
                             (if record
                               record
                               (error "Employee record not found -- GET-RECORD DIVISION-A" employee)))))
(put 'salary 'division-a (lambda (record)
                           (let ((salary (find-first
                                           (make-eq-type? 'salary)
                                           record)))
                             (if salary
                               salary
                               (error "Salary not found -- GET-SALARY DIVISION-A" record)))))

;;a Each divisions file must be a datum tagged with the divisions name.
;;  Together with the division type tag and an operation type tag
;;  we can get a procedure that knows how to do that operation for the given employee.
(define (get-record file employee)
  ((get 'record (type-tag file)) (contents file) employee))

(define test-record (get-record test-division 'henk))

;; b The record can have any structure that is handled by the salary procedure of the
;; division we dispatch the procedure from
(define (get-salary file record)
  ((get 'salary (type-tag file)) (contents record)))


(get-salary test-division test-record)

;;c
(define (find-employee-record files employee)
   (define (search fi)
     (if (null? fi)
       false
       (let ((result (with-handlers
                       ([exn:fail? (lambda (exn)
                                     false)])
                       (get-record (car fi) employee))))
         (if result
           result
           (search (cdr fi))))))
   (search files))
(find-employee-record (list test-division test-division) 'henk)

;;d
;; new implementations for the division representation for the existing operations on a type