;; The code in this file is taken from page 268 in the [A&S] text.
;; It implements a TABLE as a mutuable list structure. We restrict
;; attention to one-dimensional tables, in which each value is stored
;; under a single key. Two-dimensional tables and other kinds of
;; tables are also considered in [A&S], but we will ignore them here.

;; For a one-dimensional table, we can choose a representation of the
;; table as a list of records, each of which is represented by a pair
;; consisting of a KEY and the ASSOCIATED VALUE.  More details on this
;; representation is given on page 267 in [A&S].

;; To construct a new table, we simply create a list containing the
;; symbol *table*:

(define (make-table) (list '*table*))

;; We view *table* as the first record in the table to be constructed,
;; and *table* is really a dummy record.

;; The ASSOC procedure takes KEY and RECORDS, which is a list of records,
;; as input arguments. It returns the record which has KEY as its "car":

(define (assoc key records)
    (cond ((null? records) #f)
	  ((equal? key (caar records)) (car records))
	  (else (assoc key (cdr records)))))

;; Because ASSOC uses "equal?" instead of "=", it can recognize keys
;; that are symbols, numbers, or list structures. Note that ASSOC never
;; sees the dummy record (i.e., *table*) and does need to, because of
;; the way LOOKUP is programmed below.

;; The LOOKUP procedure takes two argument, KEY and TABLE, and returns
;; the ASSOCIATED VALUE of KEY (or #f if there is no associated value
;; for KEY):

(define (lookup key table)
    (let ((record (assoc key (cdr table))))
      (if record
	  (cdr record)
	  false)))

;; The INSERT! procedure inserts VALUE under a specified KEY in TABLE.
;; We use ASSOC to see if there is already a record in the table with
;; this key, and if there is, we set the CDR of this record to the 
;; designated new value. If there is no record with this key already,
;; we form a new record by CONS-ing the key with the value, and insert
;; it at the head of the table, but after the dummy record *table*:

(define (insert! key value table)
    (let ((record (assoc key (cdr table))))
      (if record
	  (set-cdr! record value)
	  (set-cdr! table
		    (cons (cons key value) (cdr table)))))
    'ok)



