I have placed a simple high-level utility for CLOS on ftp.cs.umbc.edu
(130.85.100.53) in /pub/Memoization/CLOS-Utilities.lisp. It basically
defines a macro that lets you do
(Define-Class Foo (Bar)
(Slot-1 Val-1)
(Slot-2 Val-2 :Doc-String "Slot-2 string"
:type fixnum
:allocation :class)
Slot-3
...
(Slot-N Val-N))
and get
(defclass Foo (Bar Named-Object)
((Slot-1 :initform Val-1 :accessor Slot-1 :initarg :Slot-1)
(Slot-2 :initform Val-1 :accessor Slot-2 :initarg :Slot-2
:type fixnum :allocation :class)
(Slot-3 :accessor Slot-3 :initarg :Slot-3)
...
(Slot-N :initform Val-N :accessor Slot-N :initarg :Slot-N)))
with the side effect that "Slot-2 string" gets set as doc string for the
generic function SLOT-2.
The "Named-Object" business automatically gives each instance a unique
NAME slot, lets you retrieve instances based on name, and lets you
retrieve a list of all instances of any given class (that is a Named-Object).
The "Def-Class" macro has the same behavior in that it provides a shorthand
method to define accessors and initargs with the same name as the slot,
but does not name the instances or keep track of the members of each
class.
A more detailed description of the utilities follows.
- Marty
(proclaim '(inline skates))
;;;============================================================================
;;; Provides a CLOS class-defining macro, and various utilities that keep
;;; track of instances based on names. 10/92-1/93 Marty Hall.
;;;
;;; A brief overview of the main user routines is given here. See the actual
;;; code for a more detailed explanation, plus functions and macros have doc
;;; strings.
;;;
;;; Define-Class: A macro that expands into defclass, allowing an abbreviated
;;; ============ class definition whereby all slots get accessors with the
;;; same name and initargs with the same name except for the
;;; colon, and an initform if a value was supplied. It
;;; optionally allows the other slot-spec keywords (eg
;;; :documentation, :allocation, :type), plus has a special
;;; keyword called :Doc-String. This specifies the doc string
;;; for the generic function of the same name as the slot. It
;;; also adds the mixin "Named-Object" to the list of
;;; superclasses, automatically adding a unique NAME slot to
;;; each instance, and creating a hash table whereby instances
;;; can be retrieved by name. This can eliminate much of the
;;; bookkeeping associated with keeping track of instances in
;;; variables, plus allows a semantic-net like structure
;;; (where instances are stored as values of slots) to be
;;; represented in permanent code, since instances do not have
;;; a print representation that can be used in code.
;;; See below for more details.
;;;
;;; Def-Class: Exactly like Define-Class except that it does not add the
;;; ========= Named-Object mixin, making instance creation faster but
;;; providing less utilities on the instances once they are made.
;;; Syntax is identical to Define-Class.
;;;
;;; Named-Object: A mixin class that gets added to the superclass list of
;;; ============ all classes defined with "Define-Class". It adds a slot
;;; and associated reader called Name. The default value of
;;; this slot will be :Foo-XX, where Foo is the class name of
;;; the instance being created, and XX is the lowest natural
;;; number whereby :Foo-XX doesn't already name an instance.
;;; All instances of Named-Objects get recorded in a hash
;;; table with the name as a key, and get a specialized
;;; print-object.
;;;
;;; Name: Reader method created automatically for all Named-Objects,
;;; ==== ie everything created via Define-Class.
;;;
;;; Get-Instance: A method that normally takes an instance name
;;; ============ (:Own-ship, 'Foo-2, etc) as an argument, and returns the
;;; instance with that name. The name can be a symbol in any
;;; package. Note that this disallows different objects with
;;; the same name in different packages, something you might
;;; want to do in many applications, but was deliberately left
;;; out for simplicity in the [D]ARPA Signature Management
;;; System (SMS), for which this utility was made. Returns NIL
;;; for a symbol that does not name an instance. If given an
;;; instance, it just returns it unchanged. NOTE ALSO the
;;; defined macro characters, such that
;;;
;;; {Foo} == (Get-Instance :Foo) and
;;; [Foo] == (Get-Instance Foo), so that for instance
;;; (Depth {Own-Ship}) == (Depth (Get-Instance :Own-Ship))
;;;
;;; Copy-Instance: Takes an instance and copies all slot values to another.
;;; ============= Assumes BOTH instances made via Define-Class in that
;;; they have identical slot names, and slot names
;;; correspond to accessors.
;;;
;;; Assign-Slot-Value: Given a quoted Instance name, Slot name, and value,
;;; ================= does (setf (Slot {Instance}) Value)
;;;
;;; Remove-Instance: takes a name or an instance, and removes the
;;; =============== corresponding entries in the hash tables.
;;;
;;; Remove-Instances: Removes (in the sense above) all instances of a
;;; ================ specified class.
;;;
;;; Direct-Instances: Takes a class name and returns all instances of
;;; ================ Named-Objects that are directly (no intervening
;;; subclasses) in that class.
;;;
;;; Instances: Takes a class name and returns all instances of Named-Objects
;;; ========= are directly or indirectly in that class. Unsorted.
;;;
;;; Instance-Names: Names of all instances of Named-Objects that are
;;; ============== directly or indirectly in specified class. Sorted
;;; alphabetically if the :Sort-p flag is set.
;;;
;;; All-Instances: All instances of Named-Objects.
;;; =============
;;;
;;; All-Instance-Names: Names of all instances of Named-Objects. Sorted
;;; ================== alphabetically if the :Sort-p flag is set.
;;;
;;; Slot-Names: Given an instance or a class name, returns a list of all
;;; ========== slots. Assuming the class was defined with Define-Class,
;;; this means that every slot SlotJ has a reader function
;;; also called SlotJ, and that every slot SlotJ also has a
;;; (setf SlotJ) writer, EXCEPT for the "Name" slot.
;;;
;;; Direct-Slot-Names: Given an instance or a class name, returns list of all
;;; ================= DIRECTLY defined slots. Ie inherited slots are not
;;; included.
;;;
;;; Has-Reader-p: Given an instance and a slot name, determines if there is
;;; ============ a reader method with the same name as the slot, as
;;; Define-Class would make automatically.
;;;
;;; Instance-Class: Given an instance name or an instance object returns a
;;; ============== symbol that is the immediate class name. Ie given
;;; 'Bear-1 returns BEAR. If the argument is neither an
;;; instance nor an instance name, this returns NIL.
;;;
;;; Subclasses: Given a class name returns the names of the direct subclasses.
;;; ========== Returns NIL if there are no subclasses OR if the supplied
;;; symbol names no class. Sorted alphabetically if the :Sort-p
;;; flag is set.
;;;
;;; Internal-Address-String: A non-standard way to get the address of an
;;; ======================= object in Symbolics or Lucid. Returns it in a
;;; string for use by a specialized print-object.
;;; NOT portable to other implementations.
;;;
;;;============================================================================