| 1 | ;;;-*- Mode: Lisp; Package: cl-user -*-
|
|---|
| 2 | ;;;
|
|---|
| 3 | ;;; example.lisp
|
|---|
| 4 | ;;;
|
|---|
| 5 | ;; Copyright © 1996 Digitool, Inc.
|
|---|
| 6 | ;; Copyright © 1992-1995 Apple Computer, Inc.
|
|---|
| 7 | ;; All rights reserved.
|
|---|
| 8 | ;; Permission is given to use, copy, and modify this software provided
|
|---|
| 9 | ;; that Digitool is given credit in all derivative works.
|
|---|
| 10 | ;; This software is provided "as is". Digitool makes no warranty or
|
|---|
| 11 | ;; representation, either express or implied, with respect to this software,
|
|---|
| 12 | ;; its quality, accuracy, merchantability, or fitness for a particular
|
|---|
| 13 | ;; purpose.
|
|---|
| 14 |
|
|---|
| 15 | ;;; Example file showing one way to save person records in a persistent heap.
|
|---|
| 16 | ;;; If your "Wood" directory is not accessible as "ccl:wood;", you
|
|---|
| 17 | ;;; will need to change the pathname in the (require "WOOD" ...) form below.
|
|---|
| 18 |
|
|---|
| 19 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|---|
| 20 | ;;;
|
|---|
| 21 | ;;; Modification history
|
|---|
| 22 | ;;;
|
|---|
| 23 | ;;; ------------- 0.96
|
|---|
| 24 | ;;; ------------- 0.95
|
|---|
| 25 | ;;; ------------- 0.94
|
|---|
| 26 | ;;; ------------- 0.93
|
|---|
| 27 | ;;; ------------- 0.9
|
|---|
| 28 | ;;; ------------- 0.8
|
|---|
| 29 | ;;; ------------- 0.6
|
|---|
| 30 | ;;; 12/09/92 bill "wood:" package prefix in commented out code.
|
|---|
| 31 | ;;; 09/14/92 bill move to CL-USER package. (require "WOOD" ...)
|
|---|
| 32 | ;;; 07/31/92 bill Matthew Cornell's typo fixes in the commented out code.
|
|---|
| 33 | ;;; ------------- 0.5
|
|---|
| 34 | ;;;
|
|---|
| 35 |
|
|---|
| 36 | (in-package "CL-USER")
|
|---|
| 37 |
|
|---|
| 38 | (eval-when (:compile-toplevel :execute :load-toplevel)
|
|---|
| 39 | (require "WOOD" "ccl:wood;wood"))
|
|---|
| 40 |
|
|---|
| 41 | ;; define the PERSON class
|
|---|
| 42 | (defclass person ()
|
|---|
| 43 | ((first-name
|
|---|
| 44 | :initarg :first-name
|
|---|
| 45 | :accessor person-first-name)
|
|---|
| 46 | (last-name
|
|---|
| 47 | :initarg :last-name
|
|---|
| 48 | :accessor person-last-name)
|
|---|
| 49 | (age
|
|---|
| 50 | :initarg :age
|
|---|
| 51 | :accessor person-age)
|
|---|
| 52 | (sex
|
|---|
| 53 | :initarg :sex
|
|---|
| 54 | :accessor person-sex)
|
|---|
| 55 | (occupation
|
|---|
| 56 | :initarg :occupation
|
|---|
| 57 | :accessor person-occupation)
|
|---|
| 58 | (ss#
|
|---|
| 59 | :initarg :ss#
|
|---|
| 60 | :accessor person-ss#)))
|
|---|
| 61 |
|
|---|
| 62 | (defmethod person-name ((self person))
|
|---|
| 63 | (concatenate 'string (person-first-name self) " " (person-last-name self)))
|
|---|
| 64 |
|
|---|
| 65 | (defmethod print-object ((object person) stream)
|
|---|
| 66 | (print-unreadable-object (object stream :type t :identity t)
|
|---|
| 67 | (format stream "~a ~a, ~a"
|
|---|
| 68 | (person-first-name object)
|
|---|
| 69 | (person-last-name object)
|
|---|
| 70 | (person-occupation object))))
|
|---|
| 71 |
|
|---|
| 72 | ;; Create a persistent heap for storing indexed PERSON instances.
|
|---|
| 73 | ;; The root object is a three element list.
|
|---|
| 74 | ;; The first element identifies the file.
|
|---|
| 75 | ;; The second element is a btree mapping social security number to person.
|
|---|
| 76 | ;; The third element is a btree mapping last name to a list of people.
|
|---|
| 77 | (defun create-person-file (&key (filename "People.wood")
|
|---|
| 78 | (if-exists :error))
|
|---|
| 79 | (let ((pheap (wood:open-pheap filename
|
|---|
| 80 | :if-exists if-exists
|
|---|
| 81 | :if-does-not-exist :create)))
|
|---|
| 82 | (setf (wood:root-object pheap)
|
|---|
| 83 | (wood:p-list
|
|---|
| 84 | pheap
|
|---|
| 85 | "People" ; Identify this file
|
|---|
| 86 | (wood:p-make-btree pheap) ; ss# -> person
|
|---|
| 87 | (wood:p-make-btree pheap) ; last-name -> (person ...)
|
|---|
| 88 | ))
|
|---|
| 89 | pheap))
|
|---|
| 90 |
|
|---|
| 91 | ; I wouldn't really look up the root for every access in a production system.
|
|---|
| 92 | (defun person-pheap-tables (pheap)
|
|---|
| 93 | (let ((root (wood:p-load (wood:root-object pheap))))
|
|---|
| 94 | (unless (and (listp root)
|
|---|
| 95 | (eql 3 (length root))
|
|---|
| 96 | (equal "People" (first root))
|
|---|
| 97 | (wood:p-btree-p (second root))
|
|---|
| 98 | (wood:p-btree-p (third root)))
|
|---|
| 99 | (error "~s does not appear to be a person file" pheap))
|
|---|
| 100 | (values (second root) (third root))))
|
|---|
| 101 |
|
|---|
| 102 | (defun store-person (pheap person)
|
|---|
| 103 | (setq person (wood::require-type person 'person))
|
|---|
| 104 | (multiple-value-bind (ss#->person last-name->person-list)
|
|---|
| 105 | (person-pheap-tables pheap)
|
|---|
| 106 | (let ((ss# (person-ss# person))
|
|---|
| 107 | (last-name (string-upcase (person-last-name person))))
|
|---|
| 108 | (unless (wood:p-btree-lookup ss#->person ss#)
|
|---|
| 109 | (setf (wood:p-btree-lookup ss#->person (person-ss# person)) person
|
|---|
| 110 | (wood:p-btree-lookup last-name->person-list last-name)
|
|---|
| 111 | (cons person
|
|---|
| 112 | (wood:p-load
|
|---|
| 113 | (wood:p-btree-lookup last-name->person-list last-name)))))))
|
|---|
| 114 | person)
|
|---|
| 115 |
|
|---|
| 116 | (defun find-person-with-ss# (pheap ss#)
|
|---|
| 117 | (let ((ss#->person (person-pheap-tables pheap)))
|
|---|
| 118 | (wood:p-load (wood:p-btree-lookup ss#->person ss#))))
|
|---|
| 119 |
|
|---|
| 120 | (defun find-people-with-last-name (pheap last-name)
|
|---|
| 121 | (multiple-value-bind (ss#->person last-name->person-list)
|
|---|
| 122 | (person-pheap-tables pheap)
|
|---|
| 123 | (declare (ignore ss#->person))
|
|---|
| 124 | (wood:p-load
|
|---|
| 125 | (wood:p-btree-lookup last-name->person-list (string-upcase last-name)))))
|
|---|
| 126 |
|
|---|
| 127 | (defun print-people-by-ss# (pheap &optional (stream t))
|
|---|
| 128 | (let ((ss#->person (person-pheap-tables pheap))
|
|---|
| 129 | (index -1))
|
|---|
| 130 | (wood:p-map-btree ss#->person
|
|---|
| 131 | #'(lambda (ss# person)
|
|---|
| 132 | (format stream "~&#~2,' d: ~a ~s~%"
|
|---|
| 133 | (incf index)
|
|---|
| 134 | ss# (wood:p-load person))))))
|
|---|
| 135 |
|
|---|
| 136 | (defun print-people-by-last-name (pheap &optional (stream t))
|
|---|
| 137 | (multiple-value-bind (ss#->person last-name->person-list)
|
|---|
| 138 | (person-pheap-tables pheap)
|
|---|
| 139 | (declare (ignore ss#->person))
|
|---|
| 140 | (wood:p-map-btree last-name->person-list
|
|---|
| 141 | #'(lambda (last-name person-list)
|
|---|
| 142 | (declare (ignore last-name))
|
|---|
| 143 | (setq person-list
|
|---|
| 144 | (sort (mapcar 'wood:p-load
|
|---|
| 145 | (wood:p-load person-list))
|
|---|
| 146 | #'string<
|
|---|
| 147 | :key 'person-first-name))
|
|---|
| 148 | (dolist (person person-list)
|
|---|
| 149 | (format stream "~&~s~%" person))))))
|
|---|
| 150 |
|
|---|
| 151 | ;; Code for creating random PERSON instances.
|
|---|
| 152 | (defparameter *first-names*
|
|---|
| 153 | '(("Alan" . M)
|
|---|
| 154 | ("Abraham" . M)
|
|---|
| 155 | ("Andrew" . M)
|
|---|
| 156 | ("Alice" . F)
|
|---|
| 157 | ("Susan" . F)
|
|---|
| 158 | ("Bob" . M)
|
|---|
| 159 | ("Hillary" . F)
|
|---|
| 160 | ("Joe" . M)
|
|---|
| 161 | ("Bill" . M)
|
|---|
| 162 | ("Matthew" . M)
|
|---|
| 163 | ("Gail" . F)
|
|---|
| 164 | ("Gary" . M)
|
|---|
| 165 | ("Doug" . M)
|
|---|
| 166 | ("Christie" . F)
|
|---|
| 167 | ("Steve" . M)
|
|---|
| 168 | ("Elizabeth" . F)
|
|---|
| 169 | ("Melissa" . F)
|
|---|
| 170 | ("Karla" . F)
|
|---|
| 171 | ("Dan" . M)
|
|---|
| 172 | ("Irving" . M)))
|
|---|
| 173 |
|
|---|
| 174 | (defparameter *last-names*
|
|---|
| 175 | '("Smith" "Jones" "Peterson" "Williams" "Kennedy" "Johnson"
|
|---|
| 176 | "Riley" "Sylversteen" "Wilson" "Cranshaw" "Ryan" "O'Neil"
|
|---|
| 177 | "McAllister"))
|
|---|
| 178 |
|
|---|
| 179 | (defparameter *occupations*
|
|---|
| 180 | '("Butcher" "Baker" "Candlestick Maker"
|
|---|
| 181 | "Engineer" "Hacker" "Tailor" "Cop" "Lawyer" "Doctor"
|
|---|
| 182 | "Dentist" "Politician" "Cashier" "Insurance Sales"
|
|---|
| 183 | "Advertising"))
|
|---|
| 184 |
|
|---|
| 185 | (defun random-person ()
|
|---|
| 186 | (multiple-value-bind (first-name last-name sex) (random-name)
|
|---|
| 187 | (make-instance 'person
|
|---|
| 188 | :first-name first-name
|
|---|
| 189 | :last-name last-name
|
|---|
| 190 | :sex sex
|
|---|
| 191 | :age (random 100)
|
|---|
| 192 | :occupation (random-element *occupations*)
|
|---|
| 193 | :ss# (random-ss#))))
|
|---|
| 194 |
|
|---|
| 195 | (defun random-element (sequence)
|
|---|
| 196 | (elt sequence (random (length sequence))))
|
|---|
| 197 |
|
|---|
| 198 | (defun random-name ()
|
|---|
| 199 | (let ((first.sex (random-element *first-names*))
|
|---|
| 200 | (last (random-element *last-names*)))
|
|---|
| 201 | (values
|
|---|
| 202 | (car first.sex)
|
|---|
| 203 | last
|
|---|
| 204 | (cdr first.sex))))
|
|---|
| 205 |
|
|---|
| 206 | (defvar *ss#s* (make-hash-table :test 'equal))
|
|---|
| 207 |
|
|---|
| 208 | (defun random-ss# ()
|
|---|
| 209 | (with-standard-io-syntax
|
|---|
| 210 | (loop
|
|---|
| 211 | (let ((ss# (write-to-string
|
|---|
| 212 | (+ (expt 10 8) (random (- (expt 10 9) (expt 10 8)))))))
|
|---|
| 213 | (unless (gethash ss# *ss#s*)
|
|---|
| 214 | (return
|
|---|
| 215 | (setf (gethash ss# *ss#s*) ss#)))))))
|
|---|
| 216 |
|
|---|
| 217 | (defun store-n-random-people (pheap n)
|
|---|
| 218 | (dotimes (i n)
|
|---|
| 219 | (store-person pheap (random-person))))
|
|---|
| 220 |
|
|---|
| 221 | #|
|
|---|
| 222 | (defun listener-stream ()
|
|---|
| 223 | "Find the stream to the listener's main pane."
|
|---|
| 224 | (let* ((listener (capi:locate-interface 'lispworks-tools:listener))
|
|---|
| 225 | (pane (and listener (capi:interface-editor-pane listener)))
|
|---|
| 226 | (stream (and pane (capi:interactive-pane-stream pane))))
|
|---|
| 227 | stream))
|
|---|
| 228 |
|
|---|
| 229 | (defvar *random-people* (loop for i from 0 below 100 collect (random-person)))
|
|---|
| 230 | (let ((stream (listener-stream)))
|
|---|
| 231 | (loop for p in (subseq *random-people* 0 18)
|
|---|
| 232 | do (format stream "~& (make-instance 'person :first-name ~s :last-name ~s :age ~s :sex '~s :occupation ~s :ss# ~s)"
|
|---|
| 233 | (person-first-name p) (person-last-name p) (person-age p)
|
|---|
| 234 | (person-sex p) (person-occupation p) (person-ss# p))))
|
|---|
| 235 |
|
|---|
| 236 | (defparameter *people*
|
|---|
| 237 | (list
|
|---|
| 238 | (make-instance 'person :first-name "Melissa" :last-name "Smith" :age #x60 :sex '\F :occupation "Cop" :ss# "232436212")
|
|---|
| 239 | (make-instance 'person :first-name "Matthew" :last-name "Wilson" :age #x5D :sex 'M :occupation "Candlestick Maker" :ss# "859110137")
|
|---|
| 240 | (make-instance 'person :first-name "Steve" :last-name "Johnson" :age #x1 :sex 'M :occupation "Cashier" :ss# "140739951")
|
|---|
| 241 | (make-instance 'person :first-name "Gail" :last-name "Wilson" :age #x4A :sex '\F :occupation "Baker" :ss# "209354283")
|
|---|
| 242 | (make-instance 'person :first-name "Dan" :last-name "Johnson" :age #x4 :sex 'M :occupation "Hacker" :ss# "809159982")
|
|---|
| 243 | (make-instance 'person :first-name "Melissa" :last-name "Jones" :age #x3 :sex '\F :occupation "Doctor" :ss# "672195544")
|
|---|
| 244 | (make-instance 'person :first-name "Alice" :last-name "Riley" :age #x4F :sex '\F :occupation "Dentist" :ss# "218397663")
|
|---|
| 245 | (make-instance 'person :first-name "Hillary" :last-name "Riley" :age #x2D :sex '\F :occupation "Insurance Sales" :ss# "573610849")
|
|---|
| 246 | (make-instance 'person :first-name "Andrew" :last-name "Peterson" :age #x5 :sex 'M :occupation "Engineer" :ss# "714724948")
|
|---|
| 247 | (make-instance 'person :first-name "Christie" :last-name "Kennedy" :age #x1E :sex '\F :occupation "Butcher" :ss# "677765239")
|
|---|
| 248 | (make-instance 'person :first-name "Karla" :last-name "O'Neil" :age #x1C :sex '\F :occupation "Butcher" :ss# "219308385")
|
|---|
| 249 | (make-instance 'person :first-name "Elizabeth" :last-name "Wilson" :age #x57 :sex '\F :occupation "Butcher" :ss# "249274187")
|
|---|
| 250 | (make-instance 'person :first-name "Elizabeth" :last-name "Riley" :age #x3B :sex '\F :occupation "Doctor" :ss# "489650772")
|
|---|
| 251 | (make-instance 'person :first-name "Irving" :last-name "Kennedy" :age #x46 :sex 'M :occupation "Doctor" :ss# "899583677")
|
|---|
| 252 | (make-instance 'person :first-name "Susan" :last-name "Riley" :age #x2B :sex '\F :occupation "Cashier" :ss# "504945523")
|
|---|
| 253 | (make-instance 'person :first-name "Hillary" :last-name "Wilson" :age #x45 :sex '\F :occupation "Politician" :ss# "437348938")
|
|---|
| 254 | (make-instance 'person :first-name "Joe" :last-name "Riley" :age #x31 :sex 'M :occupation "Politician" :ss# "170903308")
|
|---|
| 255 | (make-instance 'person :first-name "Matthew" :last-name "Riley" :age #x4B :sex 'M :occupation "Advertising" :ss# "773725302")))
|
|---|
| 256 |
|
|---|
| 257 |
|
|---|
| 258 |
|
|---|
| 259 |
|
|---|
| 260 |
|
|---|
| 261 | (delete-file "test1.wood")
|
|---|
| 262 | (setq p (create-person-file :filename "test1.wood" :if-exists :supersede))
|
|---|
| 263 | (loop for person in *people* do (store-person p person))
|
|---|
| 264 | (wood:close-pheap p)
|
|---|
| 265 |
|
|---|
| 266 |
|
|---|
| 267 | ;;; (inspect p)
|
|---|
| 268 | ;;; (WOOD::VERIFY-DEBUG-OBJECTS p)
|
|---|
| 269 |
|
|---|
| 270 | (setq pp (wood:open-pheap "test1.wood"))
|
|---|
| 271 | (print-people-by-ss# pp *trace-output*)
|
|---|
| 272 | (print-people-by-last-name pp (listener-stream))
|
|---|
| 273 | (print-people-by-last-name pp *trace-output*)
|
|---|
| 274 | (wood:close-pheap pp)
|
|---|
| 275 |
|
|---|
| 276 | |#
|
|---|
| 277 |
|
|---|
| 278 | #|
|
|---|
| 279 | (defparameter *p* (create-person-file :if-exists :supersede))
|
|---|
| 280 | ; or
|
|---|
| 281 | (defparameter *p* (wood:open-pheap "People.wood"))
|
|---|
| 282 |
|
|---|
| 283 | (store-n-random-people *p* 100)
|
|---|
| 284 |
|
|---|
| 285 | (print-people-by-ss# *p*)
|
|---|
| 286 |
|
|---|
| 287 | (print-people-by-last-name *p*)
|
|---|
| 288 |
|
|---|
| 289 | (wood:close-pheap *p*)
|
|---|
| 290 | |#
|
|---|
| 291 | ;;; 1 3/10/94 bill 1.8d247
|
|---|
| 292 | ;;; 2 3/23/95 bill 1.11d010
|
|---|