Chapter 3, Modularity, Objects, and State
Exercise 3.26
We need two things:
- Make the tree-set implementation from previous chapter - mutable.
- Use Tree-Set in table for records.
I created an entry data-structure which is nothing but a pair of key and value.
Note how abstractions play an insteresting part here - We changed the internal data-structure to tree but the external api to access table remains same.
First lets check the output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> (define tbl (make-table))
> ((tbl 'insert-proc!) 100 'hundred)
> ((tbl 'insert-proc!) 200 '2hundred)
> ((tbl 'insert-proc!) 50 'fifty)
> ((tbl 'lookup-proc) 50)
(mcons 50 'fifty)
> ((tbl 'lookup-proc) 90)
#f
> ((tbl 'insert-proc!) 50 'fiftish)
> tbl
#<procedure:...icp/ch-3/3.1.rkt:50:4>
> ((tbl 'lookup-proc) 50)
(mcons 50 'fiftish)
> ((tbl 'lookup-proc) 100)
(mcons 100 'hundred)
>
Note that, for for better readability I am returning the entry from the lookup procedure instead of returning only the value. If needed, this is a small change to return the value only.
Code:
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
#lang sicp
(define (make-tree entry left right)
(list entry left right))
(define (entry tree) (car tree))
(define (left-branch tree) (cadr tree))
(define (right-branch tree) (caddr tree))
(define (set-left-branch! tree left) (set-car! (cdr tree) left))
(define (set-right-branch! tree right) (set-car! (cddr tree) right))
(define (make-entry key value) (cons key value))
(define (key-entry entry) (car entry))
(define (value-entry entry) (cdr entry))
(define (set-key-entry! entry key) (set-car! entry key))
(define (set-value-entry! entry value) (set-cdr! entry value))
(define (adjoin-set! key value tree-set)
(cond ((null? tree-set) (make-tree (make-entry key value) '() '()))
((= key (key-entry (entry tree-set))) (set-value-entry! (entry tree-set) value))
((< key (key-entry (entry tree-set)))
(if (null? (left-branch tree-set))
(set-left-branch! tree-set (make-tree (make-entry key value) '() '()))
(adjoin-set! key value (left-branch tree-set))))
(else (if (null? (right-branch tree-set))
(set-right-branch! tree-set (make-tree (make-entry key value) '() '()))
(adjoin-set! key value (right-branch tree-set))))))
(define (lookup key tree-set)
(cond ((null? tree-set) #f)
((= key (key-entry (entry tree-set))) (entry tree-set))
((< key (key-entry (entry tree-set))) (lookup key (left-branch tree-set)))
(else (lookup key (right-branch tree-set)))))
(define (make-table)
(let ((local-table (list '*table*)))
(define (lookup-local key)
(lookup key (cdr local-table)))
(define (insert! key value)
(let ((records (cdr local-table)))
(if (null? records)
(set-cdr! local-table (make-tree (make-entry key value) '() '()))
(adjoin-set! key value records))))
(define (dispatch m)
(cond ((eq? m 'lookup-proc) lookup-local)
((eq? m 'insert-proc!) insert!)
(else (error "Unknown operation -- TABLE" m))))
dispatch))