-
Notifications
You must be signed in to change notification settings - Fork 0
/
ex3-24.scm
100 lines (75 loc) · 3.44 KB
/
ex3-24.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
(define (make-table same-key?)
; Internal state
(define table (cons 'table '()))
(define (lookup . keys)
(if (null? keys)
(error "Expected atlease one key!")
(cdr (look-up-helper keys table))))
(define (last-key? keys)
(null? (cdr keys)))
(define (subtable? record)
(and (list? (cdr record)) (not (pair? (car (cdr record))))))
(define (look-up-helper keys current-table)
(let ((result (assoc (car keys) (cdr current-table))))
(cond ((equal? result #f) (cons #f #f))
((subtable? result) (subtable-lookup (cdr keys) (cdr result)))
(else result))))
(define (subtable-lookup keys res)
(cond ((last-key? keys) (assoc (car keys) res))
((same-key? (car keys) (car res)) (subtable-lookup (cdr keys) (cdr res)))
(else (cons #f #f))))
(define (last-subtable? keys)
(equal? (length keys) 2))
(define (find-last-subtable keys records)
(if (last-subtable? keys)
(cons (cdr keys) records)
(find-last-subtable (cdr keys) (cdr records))))
(define (last-subtable-key-pair-for-insert keys current-table)
(let ((record (assoc (car keys) (cdr current-table))))
(cond ((equal? record #f) (cons keys current-table))
((subtable? record) (find-last-subtable (cdr keys) (cdr record))))))
(define (assoc key records)
(cond ((null? records) #f)
((same-key? key (caar records)) (car records))
(else (assoc key (cdr records)))))
(define (insert value . keys)
(let ((resp (look-up-helper keys table)))
(if (and resp (car resp))
(set-cdr! resp value)
(insert-helper value keys table))))
(define (insert-helper value keys current-table)
(let ((concerned-key-table-pair (last-subtable-key-pair-for-insert keys current-table)))
(let ((concerned-table (cdr concerned-key-table-pair))
(concerned-keys (car concerned-key-table-pair)))
(set-cdr! concerned-table
(cons (if (> (length concerned-keys) 1) (generate-nested-cons-structure concerned-keys value) (cons (car concerned-keys) value))
(cdr concerned-table))))))
(define (generate-nested-cons-structure keys value)
(if (null? (cdr keys))
(cons (cons (car keys) value) '())
(cons (car keys)
(generate-nested-cons-structure (cdr keys) value))))
(define (dispatch message)
(cond ((eq? message 'insert ) insert)
((eq? message 'lookup ) lookup)
((eq? message 'test ) lookup-new)
(else (error "Unknown operation"))))
dispatch)
(define table-ops (make-table equal?))
(define insert (table-ops 'insert ))
(define lookup (table-ops 'lookup ))
(define new-l (table-ops 'test ))
(define (show message)
(display message))
(define (assert cond context)
(if cond
(begin (show context) (show " Success") (newline))
(begin (show context) (error "Expectation failed"))))
(insert 100 'a 'b 'c 'k1)
(assert (equal? 100 (lookup 'a 'b 'c 'k1 )) "insert 4 keys")
(insert 200 'a 'b 'c 'k1)
(assert (equal? 200 (lookup 'a 'b 'c 'k1 )) "insert 4 keys")
(insert 1 'x)
(assert (equal? 1 (lookup 'x)) "insert 1 key")
(insert 2 'x)
(assert (equal? 2 (lookup 'x)) "insert 1 key")