Tiny Database Program
Before we can attach graphic objects, we need something to attach them to. So we begin by defining a tiny database program. A database will simply be a hash table, created by calling make-db:
(defun make-db (&optional (size 100)) (make-hash-table :size size))
Hash tables are built in to Common LISP. For our purposes, hash tables are nothing more than a fast way of doing what one does with property lists. If you want to implement this code in a dialect that doesn't support hash tables, you can use property lists, and the only difference will be in speed.
In these databases we're going to store two-part structures defined as follows:
(defstruct db-entry value attachments)
The value field will hold the LISP object we want to store in the database, and the attachments field will contain a list of functions that have to be invoked when the value field is altered. To attach a graphic object to a database entry, we will store a function referring to that object in the entry's attachments field so that when the entry is changed the graphic object will automatically be notified. Four functions for manipulating databases are shown in Listing One.
(defun db-update (db key val) (let ((entry (gethash key db))) (if entry (progn (pre-update entry) (setf (db-entry-value entry) val) (post-update entry)) (setf (gethash key db) (make-db-entry : value val)))) val) (defun db-delete (db key) (let ((entry (gethash key db))) (when entry (delete-attachments entry) (remhash key db)))) (defun db-Query (db key) (let ((entry (gethash key db))) (and entry (db-entry-value entry)))) (defun db-push (db key val) (db-update db key (cons val (db-query db key))))
The function db-uPdate adds or modifies a database entry. Note that if an update is modifying an existing entry, the change to the value field is sandwiched between calls to pre-update and post-update. These functions will spur graphic objects into action (we'll discuss them later).
The second function, db-delete, deletes an entry. The call to delete-attachments deletes any attached objects (this function will also be discussed shortly). The remaining two functions are completely straightforward.
Here we'll make a database to use in experiments later on:
> (setq our-db (make-db)) #(Hash-Table 88BBCB> > (db-update our-db 'temperature 95) 95 > (db-query our-db 'temperature) 95