Code Review
Compare your solutions
#|
Упражнение 3.25
Обобщая случаи одно- и двумерных таблиц, покажите, как можно реализовать таблицу, в которой элементы
хранятся с произвольным количеством ключей и различные значения могут храниться с различным количеством
ключей. Процедуры lookup и insert! должны принимать на входе список ключей, с которыми требуется
обратиться к таблице.
|#
(#%require rackunit
compatibility/mlist)
(define (make-table)
(let ((local-table (mlist '*table*)))
(define (assoc key records)
(cond ((null? records) #f)
((equal? key (mcar (mcar (mcar records)))) (mcar records))
(else (assoc key (mcdr records)))))
(define (lookup keys table)
(cond ((or (null? keys) (null? table)) #f)
((null? (mcdr keys))
(let ((record (assoc (mcar keys) (mcdr table))))
(if record
(mcdr (mcar record))
#f)))
(else
(let ((subtable (assoc (mcar keys) (mcdr table))))
(if subtable
(lookup (mcdr keys) subtable)
#f)))))
(define (insert! keys value table)
(define (iter! keys table)
(cond ((null? (mcdr keys))
(let ((record (assoc (mcar keys) (mcdr table))))
(if record
(set-mcdr! (mcar record) value)
(set-mcdr! table
(mcons (mlist (mcons (mcar keys) value))
(mcdr table))))))
(else
(let ((subtable (assoc (mcar keys) (mcdr table))))
(if subtable
(iter! (mcdr keys) subtable)
(let ((empty-subtable (mlist (mlist (mcar keys)))))
(set-mcdr! table (mcons empty-subtable
(mcdr table)))
(iter! (mcdr keys) empty-subtable)))))))
(if (null? keys) #f
(iter! keys table))
'ok)
(define (dispatch m)
(cond ((eq? m 'lookup-proc) (lambda (keys)
(lookup keys local-table)))
((eq? m 'insert-proc!) (lambda (keys value)
(insert! keys value local-table)))
(else (error "Unknown operation -- TABLE" m))))
dispatch))
(define (lookup table keys)
((table 'lookup-proc) keys))
(define (insert! table keys value)
((table 'insert-proc!) keys value))
(define table1 (make-table))
(check-false (lookup table1 (mlist 1)))
(insert! table1 (mlist 1) 111)
(insert! table1 (mlist 1 2) 222)
(insert! table1 (mlist 1 3) 333)
(insert! table1 (mlist 1 3 4) 444)
(check-equal? (lookup table1 (mlist 1)) 111)
(check-equal? (lookup table1 (mlist 1 2)) 222)
(check-equal? (lookup table1 (mlist 1 3)) 333)
(check-equal? (lookup table1 (mlist 1 3 4)) 444)
(check-false (lookup table1 (mlist 2)))
(insert! table1 (mlist 1 3) 3333)
(insert! table1 (mlist 1 3 4) 4444)
(check-equal? (lookup table1 (mlist 1 3)) 3333)
(check-equal? (lookup table1 (mlist 1 3 4)) 4444)