-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmulti-table.rkt
99 lines (92 loc) · 2.91 KB
/
multi-table.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
#lang racket
(require compatibility/mlist)
(provide make-table
lookup
insert!)
;; Tables are constructed from lists of (key, value)
;; pairs. They may be nested arbitrarily, in which
;; case the first element of a sublist designates
;; a subtable's key.
;; [
;; "*table*"
;;
;; [
;; "add"
;;
;; ('(complex complex) add-complex)
;; ('(rational rational) add-rational)
;; ]
;;
;; [
;; "sub"
;; ('(complex complex) add-complex)
;; ('(rational rational) add-rational)
;; ]
;; ]
(define (print-table t)
(define w 2)
(define (print-subtable t d)
(mfor-each
(lambda (x)
(let ((k (mcar x))
(v (mcdr x)))
(display (make-string (* d w) #\space))
(display k)
(display ":")
(if (not (mlist? v))
(begin
(display " ")
(display v)
(display "\n"))
(begin
(display "\n")
(print-subtable v (add1 d))))))
t))
(print-subtable t 0))
(define (make-table)
(let ((local-table (mlist '*table*)))
(define (lookup keys)
(define (lookup-one keys table)
(let ((key (car keys))
(rest (cdr keys))
(records (mcdr table)))
(let ((record (massoc key records)))
(if (not record)
false
(if (null? rest)
(mcdr record)
(lookup-one rest record))))))
(lookup-one keys local-table))
(define (insert! value keys)
(define (insert-one! keys table)
(let ((key (car keys))
(rest (cdr keys))
(records (mcdr table)))
(let ((record (massoc key records)))
(if (null? rest)
(if record
(set-mcdr! record value)
(set-mcdr! table (mcons (mcons key value) records)))
(cond
((not record)
(begin
(set-mcdr! table (mcons (mlist key) records))
(insert-one! rest (mcar (mcdr table)))))
((mlist? record)
(insert-one! rest record))
((mpair? record)
(begin
(set-mcdr! record '())
(insert-one! rest record)))
(else (error "INSERT -- unrecognized record type"
record)))))))
(insert-one! keys local-table))
(define (dispatch m)
(cond ((eq? m 'lookup) lookup)
((eq? m 'insert!) insert!)
(else (error "Unknown operation -- TABLE" m))))
dispatch))
(define (lookup table key . keys)
((table 'lookup) (cons key keys)))
(define (insert! table value key . keys)
((table 'insert!) value (cons key keys)))