I am attempting to answer the following exercise.
Write a macro function OUR-IF that translates the following macro calls.
(our-if a then b) translates to (cond (a b)) (our-if a then b else c) translates to (cond (a b) (t c))
My solution is the following:
(defmacro our-if (test then then-clause &optional else else-clause)
(if (equal 'else else)
`(cond (,test ,then-clause) (t ,else-clause))
`(cond (,test ,then-clause))))
That works fine, but I'm not totally satisfied by it. There's no syntax checking on the "then" and "else" arguments. Then could be anything. And if I gave the wrong symbol for "else", I'd get the wrong behaviour. The symbols aren't even checked to be symbols.
I could model them as keyword arguments and get close, but that's not exactly right either. It reminds me of the LOOP macro, which is a much more complicated example of the same thing. That made me wonder: how does LOOP do it? Maybe there's some pattern for "mini languages in macro arguments". But I couldn't find anything.
I found the hyperspec page for LOOP which confirms that the grammar is complicated. But I don't know if there's a nice way to implement it.