From: Ken Tilton
Subject: (fix 'defclass) -> DEFKENNY
Date: 
Message-ID: <snfpg.38$Dk.15@fe10.lga>
Linebreaks are your problem, as are nose demons. Your hard drive, 
however, should be safe:

(defmacro defkenny (class superclasses &rest class-spec)
   `(defclass ,class ,superclasses
      ,@(let (definitargs class-options slots)
          (loop with skip
              for (spec next) on class-spec
              if skip
              do (setf skip nil)
              else do (etypecase spec
                        (cons
                         (cond
                          ((keywordp (car spec))
                           (assert (find (car spec) '(:documentation 
:metaclass)))
                           (push spec class-options))
                          ((find (cadr spec) '(:initarg :type :initform 
:allocation :reader :writer :accessor :documentation))
                           (push (apply 'defkenny-canonicalize-slot 
spec) slots))
                          (t ;; must be shortform: (slotname initform 
&rest slotdef-key-values)
                           (push (apply 'defkenny-canonicalize-slot
                                   (list* (car spec) :initform (cadr 
spec) (cddr spec))) slots))))
                        (keyword
                         (setf definitargs (append definitargs (list 
spec next)))
                         (setf skip t))
                        (symbol (push (list spec :initform nil
                                        :initarg (intern (symbol-name 
spec) :keyword)
                                        :accessor spec) slots)))
              finally
                (return (list* (nreverse slots)
                          (delete-if 'null
                            (list* `(:default-initargs ,@definitargs)
                              (nreverse class-options)))))))))

(defun defkenny-canonicalize-slot (slotname
                                  &key
                                  (type nil type-p)
                                  (initform nil initform-p)
                                  (initarg (intern (symbol-name 
slotname) :keyword))
                                  (documentation nil documentation-p)
                                  (unchanged-if nil unchanged-if-p)
                                  (reader slotname reader-p)
                                  (writer `(setf ,slotname) writer-p)
                                  (accessor slotname accessor-p)
                                  (allocation nil allocation-p))
   (list* slotname :initarg initarg
     (append
      (when type-p (list :type type))
      (when initform-p (list :initform initform))
      (when unchanged-if-p (list :unchanged-if unchanged-if))
      (when reader-p (list :reader reader))
      (when writer-p (list :writer writer))
      (when (or accessor-p
              (not (and reader-p writer-p)))
        (list :accessor accessor))
      (when allocation-p (list :allocation allocation))
      (when documentation-p (list :documentation documentation)))))

#+testkenny
(progn
   (defclass md-test-super ()())

   (defkenny defkenny-test (md-test-super)
     (aaa :initform nil :initarg :aaa :accessor aaa)
     (aa2 :documentation "hi mom")
     bbb
     (ccc 42 :allocation :class)
     (ddd (c-in nil))
     :superx 42 ;; default-initarg
     (:documentation "as if!")))

=>
(defclass defkenny-test (md-test-super)
   ((aaa :initarg :aaa :initform nil :accessor aaa)
    (aa2 :initarg :aa2 :accessor aa2 :documentation "hi mom")
    (bbb :initform nil :initarg :bbb :accessor bbb)
    (ccc :initarg :ccc :initform 42 :accessor ccc :allocation :class)
    (ddd :initarg :ddd :initform (c-in nil) :accessor ddd))
   (:default-initargs
       :superx 42)
   (:documentation "as if!"))

You are welcome.

   kenny

-- 
Cells: http://common-lisp.net/project/cells/

"I'll say I'm losing my grip, and it feels terrific."
    -- Smiling husband to scowling wife, New Yorker cartoon

From: ········@gmail.com
Subject: Re: (fix 'defclass) -> DEFKENNY
Date: 
Message-ID: <1151711554.165990.131790@h44g2000cwa.googlegroups.com>
Ken Tilton wrote:
> Linebreaks are your problem, as are nose demons. Your hard drive,
> however, should be safe:
>
> (defmacro defkenny (class superclasses &rest class-spec)
>    `(defclass ,class ,superclasses
>       ,@(let (definitargs class-options slots)
>           (loop with skip
>               for (spec next) on class-spec
>               if skip
>               do (setf skip nil)
>               else do (etypecase spec
>                         (cons
>                          (cond
>                           ((keywordp (car spec))
>                            (assert (find (car spec) '(:documentation
> :metaclass)))
>                            (push spec class-options))
>                           ((find (cadr spec) '(:initarg :type :initform
> :allocation :reader :writer :accessor :documentation))
>                            (push (apply 'defkenny-canonicalize-slot
> spec) slots))
>                           (t ;; must be shortform: (slotname initform
> &rest slotdef-key-values)
>                            (push (apply 'defkenny-canonicalize-slot
>                                    (list* (car spec) :initform (cadr
> spec) (cddr spec))) slots))))
>                         (keyword
>                          (setf definitargs (append definitargs (list
> spec next)))
>                          (setf skip t))
>                         (symbol (push (list spec :initform nil
>                                         :initarg (intern (symbol-name
> spec) :keyword)
>                                         :accessor spec) slots)))
>               finally
>                 (return (list* (nreverse slots)
>                           (delete-if 'null
>                             (list* `(:default-initargs ,@definitargs)
>                               (nreverse class-options)))))))))
>
> (defun defkenny-canonicalize-slot (slotname
>                                   &key
>                                   (type nil type-p)
>                                   (initform nil initform-p)
>                                   (initarg (intern (symbol-name
> slotname) :keyword))
>                                   (documentation nil documentation-p)
>                                   (unchanged-if nil unchanged-if-p)
>                                   (reader slotname reader-p)
>                                   (writer `(setf ,slotname) writer-p)
>                                   (accessor slotname accessor-p)
>                                   (allocation nil allocation-p))
>    (list* slotname :initarg initarg
>      (append
>       (when type-p (list :type type))
>       (when initform-p (list :initform initform))
>       (when unchanged-if-p (list :unchanged-if unchanged-if))
>       (when reader-p (list :reader reader))
>       (when writer-p (list :writer writer))
>       (when (or accessor-p
>               (not (and reader-p writer-p)))
>         (list :accessor accessor))
>       (when allocation-p (list :allocation allocation))
>       (when documentation-p (list :documentation documentation)))))
>
> #+testkenny
> (progn
>    (defclass md-test-super ()())
>
>    (defkenny defkenny-test (md-test-super)
>      (aaa :initform nil :initarg :aaa :accessor aaa)
>      (aa2 :documentation "hi mom")
>      bbb
>      (ccc 42 :allocation :class)
>      (ddd (c-in nil))
>      :superx 42 ;; default-initarg
>      (:documentation "as if!")))
>
> =>
> (defclass defkenny-test (md-test-super)
>    ((aaa :initarg :aaa :initform nil :accessor aaa)
>     (aa2 :initarg :aa2 :accessor aa2 :documentation "hi mom")
>     (bbb :initform nil :initarg :bbb :accessor bbb)
>     (ccc :initarg :ccc :initform 42 :accessor ccc :allocation :class)
>     (ddd :initarg :ddd :initform (c-in nil) :accessor ddd))
>    (:default-initargs
>        :superx 42)
>    (:documentation "as if!"))



(defmacro my-defkenny (name superclasses &body class-spec)
  (labels ((make-keyword (sym)
	     (intern (symbol-name sym)
		     (symbol-package :keyword)))
	   (ensure-initarg (sd)
	     (when sd
	       (if (member :initarg sd)
		   sd
		   (let ((n (car sd)))
		`(,n :initarg ,(make-keyword n) ,@(cdr sd))))))
	   (make-accessor (sym)
	     (intern (concatenate 'string
				  (string sym)
				  (string '#:-of))
		     (symbol-package sym)))
	   (ensure-accessor (sd)
	     (when sd
	       (if (member :accessor sd)
		    sd
		    (let ((n (car sd)))
		`(,n :accessor ,(make-accessor n) ,@(cdr sd))))))
	   (expand-lazy-initform (sd)
	     (if (and (cdr sd)
		      (not (keywordp (second sd))))
		 `(,(car sd) :initform ,@(cdr sd))
		 sd))
	   (ensure-listp (sd)
	     (if (listp sd)
		 sd
		 (list sd)))
	   (isolate-class-and-slot-specs (spec)
	     (flet ((fn (s)
		      (and (listp s)
			   (keywordp (car s)))))
	       (values (remove-if #'fn spec)
		       (remove-if (complement #'fn) spec))))
	   (re-roll-naked-default-initargs (spec)
	     (when spec
	       (if* (keywordp (car spec))
		  then (cons (list :default-initargs
				   (first spec)
				   (second spec))
			     (re-roll-naked-default-initargs (cddr spec)))
		  else (cons (car spec)
			     (re-roll-naked-default-initargs (cdr spec)))))))
    (multiple-value-bind (slot-specs isolated-class-specs)
	(isolate-class-and-slot-specs
	 (re-roll-naked-default-initargs class-spec))
      `(defclass ,name ,superclasses
	 ,(map 'list
	       #'(lambda (s)
		   (ensure-accessor
		    (ensure-initarg
		     (expand-lazy-initform
		      (ensure-listp s)))))
	       slot-specs)
	 ,@isolated-class-specs))))

;(defkenny defkenny-test (md-test-super)
;      (aaa :initform nil :initarg :aaa :accessor aaa-of)
;      (aa2 :documentation "hi mom")
;      bbb
;      (ccc 42 :allocation :class)
;      (ddd (c-in nil))
;      :superx 42 ;; default-initarg
;      (:documentation "as if!")))
;
; =>
;
; (defclass defkenny-test (md-test-super)
;    ((aaa :initarg :aaa :initform nil :accessor aaa-of)
;     (aa2 :initarg :aa2 :accessor aa2-of :documentation "hi mom")
;     (bbb :initform nil :initarg :bbb :accessor-of bbb)
;     (ccc :initarg :ccc :initform 42 :accessor-of ccc :allocation
:class)
;     (ddd :initarg :ddd :initform (c-in nil) :accessor-of ddd))
;    (:default-initargs
;        :superx 42)
;    (:documentation "as if!"))

;caveat: generated accessors are SLOT-NAME-OF, not SLOT-NAME

;I'm not sure I really dig having :superx 42 => (:default-initargs
:superx 42)... also, what if I want a slot's initarg to be a keyword?

;nick

>
> You are welcome.
>
>    kenny
>
> --
> Cells: http://common-lisp.net/project/cells/
>
> "I'll say I'm losing my grip, and it feels terrific."
>     -- Smiling husband to scowling wife, New Yorker cartoon
From: Maciek Pasternacki
Subject: Re: (fix 'defclass) -> DEFKENNY
Date: 
Message-ID: <87k64nrc0f.fsf@japhy.fnord.org>
Little update: allows to use any form defining a class (like UCW's
(DEFCOMPONENT)) and to use any slot-definition arguments (to allow
e.g. UCW's :COMPONENT or AllegroCache's :INDEX args.

(macroexpand-1 '(kenny defcomponent foo (standard-component)
                  (bar (make-instance 'whatever))
                  (baz :component 'xyzzy)))

=> (DEFCOMPONENT FOO (STANDARD-COMPONENT)
     ((BAR :INITARG :BAR :ACCESSOR BAR :INITFORM
      (MAKE-INSTANCE 'WHATEVER))
      (BAZ :INITARG :BAZ :ACCESSOR BAZ :INITFORM NIL :COMPONENT 'XYZZY))
      (:DEFAULT-INITARGS))

On Sweetmorn, Confusion 35, 3172 YOLD, Ken Tilton wrote:

> (defmacro defkenny (class superclasses &rest class-spec)
>   `(defclass ,class ,superclasses
  (defmacro kenny (class-defining-form class superclasses &rest class-spec)
    `(,class-defining-form ,class ,superclasses
[cut]
>                          ((find (cadr spec) '(:initarg :type :initform
> :allocation :reader :writer :accessor :documentation))
                           ((keywordp (cadr spec))
[cut]
(let ((marker (gensym)))
  (defun defkenny-canonicalize-slot (slotname &rest args)
    (macrolet ((pull-arg (arg-name default)
                 `(if (eq marker (getf args ,arg-name marker))
                      (list ,arg-name ,default)
                      (prog1
                          (list ,arg-name (getf args ,arg-name))
                        (remf args ,arg-name)))))
     (list* slotname
            (append
             (pull-arg :initarg (intern (symbol-name slotname) :keyword))
             (when (or (eq marker (getf args :reader marker))
                       (eq marker (getf args :writer marker)))
               (pull-arg :accessor slotname))
             (pull-arg :initform nil)
             args)))))

-- 
-><- This signature intentionally left blank. -><-