Defmacro with defclass

I have a class in Common Lisp:

(defclass my-cool-class() ((variable1 :initarg :variable1 :accessor variable1 :initform (error "Must supply value to variable1")) (variable2 :initarg :variable2 :accessor variable2 :initform (error "Must supply value to variable2")) 

I wanted to create a macro that would simplify this input redundancy

 (defmacro make-slot (slot-name) `(slot-name :initarg :,slot-name :accessor :,slot-name :initform (error "Must supply value"))) 

In the end, I would like (defclass my-cool-class () (make-slots' (foo bar baz)) and automatically get foo, bar and baz as time intervals.

But, when I went to do macroexpand-1 in make-slot, boy, I realized that I had read errors.

The first was the "illegal terminating character after the colon ...", and then it kept going.

SBCL 1.0.37.

edit: the examples are syntactically correct on the system, I did some editing before I copied.


Six months later -

 (defun build-var (classname var) (list var :initform nil :accessor (intern (concatenate 'string (string classname) "-" (string var))) :initarg (intern (string var) :keyword))) (defun build-varlist (classname varlist) (loop for var in varlist collect (build-var classname var))) (defmacro defobject (name &rest varlist) "Defines a class with a set of behavior. Variables are accessed by name-varname. (defobject classname v1 v2 v3) " `(defclass ,name () ,(build-varlist name varlist))): 

Two and a half years later.

I discovered a six month old code in the wild elsewhere. Although I am flattered, it also reminds me of that.

If you like this idea, I save this code in the garden: https://github.com/pnathan/defobject . As before, its goal is to create CLOS classes with minimal repetitive typing. A similar system exists as DEFCLASS-STAR. Interested parties are encouraged to read them.

+7
macros lisp common-lisp
source share
4 answers

You cannot put macros in code where you want. Read the syntax for the construct in CLHS.

For example, you cannot do:

 (defun foo (make-arg-list 'a 'b) ab) 

DEFUN expects an arglist, not a function that creates an arglist.

Lisp extends macros where Lisp forms are expected. Where other lists are expected (such as a list of slots), Lisp is not macrodecay.

A similar DEFCLASS expects a list of slots, not a function that creates a list of slots. Like a list of slots, DEFCLASS expects each slot to be either a name or a list describing the slot.

See DEFCLASS syntax: http://www.lispworks.com/documentation/HyperSpec/Body/m_defcla.htm

You also cannot put commas where you want.

Probabaly can help with the basic Lisp book. Read about Lisp syntax.

 :,foo 

above does not make sense.

The comma operator places items in countdown lists. It does not put elements in characters.

If you want to create a character, you need to call INTERN or MAKE-SYMBOL.

Decision

Write a MY-DEFCLASS macro that allows for shorter syntax and extends to DEFCLASS. There are already DEFCLASS * macros that do something similar in libraries.

+5
source share

I usually use something like this

 (defmacro mydefclass (name fields) `(defclass ,name () ,(let ((res nil)) (dolist (f fields) (let* ((fname (symbol-name f)) (kw (intern fname :keyword))) (push `(,f :accessor ,kw :initarg ,kw :initform (error ,(format NIL "Must supply value to ~a" fname))) res))) (nreverse res)))) 

and then

 (mydefclass foo (xyz)) 

Adding some logic to handle the need for custom slots is very simple (for example, you can copy the input to the extension when the field is a list, not a symbol)

+3
source share

According to Rainer, macros expand only when a function call is acceptable.

What I did to limit the boiler plate that I need to type when defining the slots is to have two editor macros, one for slots with a reader and one for slots with an accessory (I rarely have slots with separate ones but if I did it, I would have to write it manually).

+2
source share

Macros expand recursively from top to bottom. In your example, the defclass macro defclass expanded first - before your make-slot macro. Code that extends defclass does not expect an defclass make-slot macro β€” it expects a slot definition.

According to others, reader errors are due to the fact that `:,symbol not valid Lisp. But it's easy enough to just pass the keyword into the macro first.

0
source share

All Articles