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 redundancy of typing
(defmacro make-slot (slot-name)
`(slot-name
:initarg :,slot-name
:accessor :,slot-name
:initform (error "Must supply value")))
Eventually I'd like to have (defclass my-cool-class () (make-slots '(foo bar baz)) and get foo, bar, and baz out as slots automagically.
But, when I went to do a macroexpand-1
of make-slot, boy howdy did I get reader errors.
The first one was "illegal terminating character after a colon..." and then it kept going.
SBCL 1.0.37.
edit: the examples are syntactically correct on the system, I did some redaction 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 the six-month-old code in the wild elsewhere. While I'm flattered, it also reminds me to update this.
If you like this idea, I keep this code gardened at: https://github.com/pnathan/defobject . As before, its goal is to produce CLOS classes with the minimum of repetitive typing. A similar system exists called DEFCLASS-STAR. Interested parties are advised to review both.
You can't put macros in code where you want. Read the syntax for a construct in CLHS.
For example you can't do:
(defun foo (make-arg-list 'a 'b) a b)
DEFUN expects an arglist and not a function that creates an arglist.
Lisp expands macros, where Lisp forms are expected. Where other lists (for example a list of slots) are expected, Lisp does not macroexpand.
Similar DEFCLASS expects a list of slots and not a function that creates a list of slots. Similar for the list of slots, DEFCLASS expects each slot to be either a name or a list describing the slot.
See the syntax of DEFCLASS: http://www.lispworks.com/documentation/HyperSpec/Body/m_defcla.htm
You can't also put commas where you want.
Probabaly a basic Lisp book might help. Read about the Lisp syntax.
:,foo
above is not meaningful.
The comma operator puts items into backquoted lists. It does not put items into symbols.
If you want to create a symbol, you need to call INTERN or MAKE-SYMBOL.
Solution
Write a MY-DEFCLASS macro that allows a shorter syntax and expands into DEFCLASS. There are already DEFCLASS* macros that are doing something like that in libraries.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With