From: Marcus Daniels
Subject: computed types vs. slot definitions
Date: 
Message-ID: <2cvoiv$i8r@ursula.ee.pdx.edu>
I've got the following classes.

(defclass dosim ()
  ((ID :type ID-string)
   (BOC :type BOC-integer)
   (job :type job-integer)))

(defclass dosim-nz (dosim)
  ((company :type company-string-nz)))

(defclass dosim-us (dosim)
  ((company :type company-string-us)))

It was convienient to have a
single archiving method for `dosim' which assumed dosim would
be an abstract superclass (the format of the data
was the same for `nz' and `us').

(defmethod read-object ((self dosim) stream)
  (let (word val)
    (setq word (read-word stream))
    (check-type word ID-string)
    (setf (slot-value self 'ID) word)
       
    (setq word (read-word stream))
    (eval (check-company-type-cmd word self))    ;; <<--- ugly hack

.....

I'd like to type-check `company' by looking up the slot definition type
and performing a `check-type'.  I couldn't figure out how to make
`deftype' do a computed-type, so I used the following (with the `eval'
ugly-hack above).  

(defun find-slot-type (class slot-name)
  (dolist (slot (class-slots class) nil)
	    (when (eql slot-name (slot-definition-name slot))
		  (return (slot-definition-type slot)))))

(defmacro check-company-type-cmd (str object)
  ``(check-type ,,str ,(find-slot-type (class-of ,object) 'company)))

How should have I done this?
From: Len Charest
Subject: Re: computed types vs. slot definitions
Date: 
Message-ID: <1993Nov24.211934.23464@jpl-devvax.jpl.nasa.gov>
In article ···@ursula.ee.pdx.edu, ······@ursula.ee.pdx.edu (Marcus Daniels) writes:
>(defmethod read-object ((self dosim) stream)
>  (let (word val)
>    (setq word (read-word stream))
>    (check-type word ID-string)
>    (setf (slot-value self 'ID) word)
>       
>    (setq word (read-word stream))
>    (eval (check-company-type-cmd word self))    ;; <<--- ugly hack
>
>(defmacro check-company-type-cmd (str object)
>  ``(check-type ,,str ,(find-slot-type (class-of ,object) 'company)))
>
>How should have I done this?

You wrote CHECK-COMPANY-TYPE-CMD as a macro and then you've forced an
extra level of evaluation on the macroexpansion (hence the double
backquotes). Why not just write a regular function that calls TYPEP,
e.g.

(defun check-company-type (str object)
  (let ((target-type (find-slot-type (class-of object) 'company)))
    (or (typep str target-type)
        (error "Expecting a datum of type ~s for ~s."
               target-type str))))

This function does *not* need to be wrapped with an EVAL. Note that
CHECK-TYPE is a macro whose expansion includes a call to TYPEP or
something that behaves like TYPEP.

---

..................................Len Charest, Jr.
.................JPL Artificial Intelligence Group
·································@aig.jpl.nasa.gov