source: branches/lispworks/example.lisp@ 32

Last change on this file since 32 was 6, checked in by Gail Zacharias, 17 years ago

Working lispworks version, but now doesn't load in MCL (yet).

  • Property svn:eol-style set to native
File size: 11.1 KB
Line 
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
Note: See TracBrowser for help on using the repository browser.