(defclass <classed-local-slot-description> (<local-slot-description>) ((contents-class initform <object> initarg contents-class reader classed-local-slot-description-contents-class)) metaclass <slot-description-class>)
The classed-local-slot-description class inherits the normal slots from <local-slot-description> and adds somewhere to keep track of the allowed class of its contents.
To police the class (type) constraint, we must check that whenever a value is written to a slot with this class—that the value is of the specified kind. we therefore want a new method on compute-primitive-writer-using-slot-description. (defmethod compute-primitive-writer-using-slot-description ((csd <classed-local-slot-description>) cl lst) (let ((std-writer (call-next-method)) (contents-cl (classed-local-slot-description-contents-class csd))) (lambda (obj val) (if (subclassp (class-of val) contents-cl) (std-writer obj val) (error "invalid class of value for slot" some-error 'object obj 'sd csd 'val val)))))
The call to the standard writer is reached only if the value satisfies the class constraint. It just means the value is acceptable—go ahead and do whatever you normally do to put the slot value inside.
All that remains is how to use one of these slots in a class. The example you give can be done as follows—but remember that defclass must be used instead of defstruct because the latter does not support user-defined slot classes.
(defclass <person> () ((age slot-class <classed-local-slot-description> initarg age slot-initargs ('contents-class <integer>) accessor age) (name slot-class <classed-local-slot-description> slot-initargs ('contents-class <string>) accessor name) (ordinary-slot initform 'bleagh)) )
The slots age and name are of the new class of slot with their contents class set to integer and string respectively. Of course, other slots with different classes of slot description may also be defined.
Now, we may type the following:
(setq i (make <person>)) ((setter age) i 27)
which is fine and (age i) will return 27.
((setter age) i 'not-a-number)
but this signals an error. Thanks to Luis Mandel for prompting this example.