From: ···········@gmail.com
Subject: Macro to generate defclass expressions
Date: 
Message-ID: <1181706095.876350.126780@g37g2000prf.googlegroups.com>
Hello,

I have built a macro to generate defclass expressions and would like
to get feedback as to its quality.

I had difficulty in coming up with an adequate method of generating
the :accessor value in the defclass expression - I found this Usenet
posting from 1997 which helped me solve that part -
http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/1adaa2902a5db6df/5cbd81811c491caf?lnk=gst&q=defclass+macro+accessor&rnum=14#5cbd81811c491caf

Anyway, here is a simplified version of my macro:

(defmacro def-persinx-class (name slots)
	   (flet ((make-slot-accessor (class slot)
		    (intern (concatenate 'string (symbol-name class) "-" (symbol-
name slot)))))
	     `(defclass name ()
	       ,(mapcar #'(lambda (slot)
			    (list slot :accessor (make-slot-accessor name slot)))
			slots))))

=========================

The intention is that an expression such as:

(def-persinx-class person (first last address))

expands into:

(defclass person ()
   ((first :accessor person-first)
    (last :accessor person-last)
    (address :accessor person-address)))

===========================

My question is twofold:
1) Is the make-accessor-slot kosher? What are the possible side-
effects of the way in which I "intern" and "symbol-name"?

2) Any other comments as to the quality of the macro?

Joubert

From: Geoff Wozniak
Subject: Re: Macro to generate defclass expressions
Date: 
Message-ID: <1181773553.278930.56880@d30g2000prg.googlegroups.com>
On Jun 12, 11:41 pm, ············@gmail.com" <···········@gmail.com>
wrote:
> My question is twofold:
> 1) Is the make-accessor-slot kosher? What are the possible side-
> effects of the way in which I "intern" and "symbol-name"?
>

I've always been partial to FORMAT in lieu of CONCATENATE.

(format nil "~A-~A" (symbol-name class) (symbol-name slot))

or perhaps just

(format nil "~A-~A" class slot)

As for the macro, it doesn't handle symbols that have no package or
are part of the keyword package in the way you probably intended.

CL-USER> (macroexpand-1 '(def-persinx-class #:foo (:bar :baz)))
(DEFCLASS #:FOO ()
  ((:BAR :ACCESSOR FOO-BAR)
   (:BAZ :ACCESSOR FOO-BAZ)))

Depending on how you intend to use it, this may not be an issue.

It probably wouldn't hurt to be explicit about what package the
symbols are interned in, either.
From: Thomas A. Russ
Subject: Re: Macro to generate defclass expressions
Date: 
Message-ID: <ymify4vqvvr.fsf@sevak.isi.edu>
············@gmail.com" <···········@gmail.com> writes:

> =========================
> 
> The intention is that an expression such as:
> 
> (def-persinx-class person (first last address))
> 
> expands into:
> 
> (defclass person ()
>    ((first :accessor person-first)
>     (last :accessor person-last)
>     (address :accessor person-address)))

I've never been a great fan of concatenating the class name onto the
slot name for accessor functions.  The main reason is that you then need
to remember where in the hierarchy of classes particular slots are
defined.  It also means if you move them around, then the slot accessor
names change.

So if you want to extend this class:

(defclass child (person) 
  ((guardian :accessor child-guardian)))

(defclass school-child (child)
  ((school :accessor school-child-school)))

Then you end up needing to use different accessors for the different
"levels" of inheritance:

(let ((c (make-instance 'school-child)))
  ...
  (list (person-name c)
        (child-guardian c)
        (school-child-school c)))




-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: ···········@gmail.com
Subject: Re: Macro to generate defclass expressions
Date: 
Message-ID: <1181864016.475399.97630@i38g2000prf.googlegroups.com>
Thanks for the input.

Taking the above recommendations into account, I've updated my macro
that generates Elephant persistent classes to the following:

(defmacro def-persinx-class (name slots)
	   (flet ((make-keyword (s)
		    (let ((name (ctypecase s
				  (symbol (symbol-name s))
				  (string s))))
		      (intern name :keyword))))
	     `(ele:defpclass ,name ()
	       ,(mapcar #'(lambda (slot)
			    (list slot :accessor slot :initarg (make-keyword slot)))
			slots))))

In summary, the slot accessors no longer have the class name prefix,
and I've added an :initarg value.

The following is an example macro expansion:

(macroexpand-1 '(def-persinx-class automobile (model make color
passengersize)))

(ELEPHANT:DEFPCLASS AUTOMOBILE NIL
                    ((MODEL :ACCESSOR MODEL :INITARG :MODEL)
                     (MAKE :ACCESSOR MAKE :INITARG :MAKE)
                     (COLOR :ACCESSOR COLOR :INITARG :COLOR)
                     (PASSENGERSIZE :ACCESSOR PASSENGERSIZE :INITARG
                                    :PASSENGERSIZE))
                    (:INDEX T))

(note - ele:defpclass is the Elephant macro to create persistent
classes)

Joubert
From: Vassil Nikolov
Subject: Re: Macro to generate defclass expressions
Date: 
Message-ID: <kawsy6t10g.fsf@localhost.localdomain>
On Thu, 14 Jun 2007 23:33:36 -0000, ············@gmail.com" <···········@gmail.com> said:
| ...
| 		                (ctypecase s
| 				  (symbol (symbol-name s))
| 				  (string s))

  (string 'foo) <=> (symbol-name 'foo)
  (string "foo") <=> "foo"

  ---Vassil.


-- 
The truly good code is the obviously correct code.