title: Using a quoted list of slots for Peter Seibel's defclass macro
body: <p>I am using the defclass macro from <a href="http://www.gigamonkeys.com/book/practical-parsing-binary-files.html" rel="nofollow noreferrer">Practical Common Lisp</a>, which takes as argument a list of symbols.</p>
  
  <p>I would like to change the macro in order to let it accept a quoted list of symbols. This has the benefit of having thenm defined as constants that can be used in other convenience functions, e.g. <a href="https://stackoverflow.com/a/60902139/2336738">here</a>. I confused myself in trying to get this done.</p>
  
  <p>My use case is following:</p>
  
  <pre><code>(defconstant state-slots '(unit motion mode moc-offset woc-pos woc-inc feed spindle))
  
  ;; would like to use the quoted list here:
  (defclass-by-slots gc-state (unit       ; :mm(=G21) :inch(=G20)
                               motor      ; nil :on 
                               motion     ; :jog(=G0) :lin(=G1) :cw(=G2) :ccw(=G3)        
                               mode       ; :abs(=G90) :inc(=G91)
                               moc-offset ; woc-zero(xyz, mm) from moc-zero
                               woc-pos    ; woc-pos(xyz, mm) from woc-zero
                               woc-inc    
                               feed
                               spindle))
  
  ;; can use quoted slot list when using a convenience function, e.g:
  (defun format-by-slots (o slots &amp;optional str-type)
    (let* ((f (lambda (s$) (eval (format-slot o s$))))
           (str-type (string-upcase str-type))
           (r (concatenate
               'string
               (format nil "~A (~A)" o (class-of o))
               (reduce (lambda (s1 s2) (concatenate 'string s1 s2))
                       (loop for s in slots
                             when (funcall f s) collect it)
                       :from-end t :initial-value (format nil "~%")))))
      (if str-type
          (ppcre:regex-replace-all
           (format nil "^#&lt;~A \\{(\\d|[A-F])+\\}&gt; " str-type) 
           r
           (format nil "#&lt;~A {...}&gt; " str-type))
          r)))
  </code></pre>
  
  <p>I am using this for several classes defined by different slots.</p>
  
  <p>The nuisance is that I cannot have defined the slots uniformly for the type definition and the convenience functions which is source of annoying errors.</p>
  
  <p>Solution based on [Rainer Joswig's answer] (<a href="https://stackoverflow.com/a/61154538/2336738">https://stackoverflow.com/a/61154538/2336738</a>):</p>
  
  <pre><code>(defmacro def-my-class (name supers slots-symbol)
    "The value of a symbol of slots-symbol is used as the
    list of slots."
    `(defclass ,name ,supers
       ,(if (and (symbolp slots-symbol)
                 (symbol-value slots-symbol)
                 (listp (symbol-value slots-symbol)))
            (mapcar #'slot-&gt;defclass-slot (symbol-value slots-symbol))
            (error "~a is not a symbol which names a list of slot names" slots-symbol))))
  </code></pre>