Dear all, I now have a preliminary macro
(defmacro key-if(test &key then else)
`(cond (,test
,then)
(t,else)))
and it is now correctly working as
> (key-if (> 3 1) :then 'ok)
OK
> (key-if (< 5 3) :else 'ok)
OK
> (key-if (> 3 1) :else 'oops)
NIL
> (key-if (> 3 1) :else 'oops :then 'ok)
OK
Now I want to extend it a bit, which means I want to have arbitrary number of arguments followed by :then or :else (the keyword), so it will work like
> (key-if (> 3 1) :then)
NIL
> (key-if (> 3 1) :else 'oops :then (print 'hi) 'ok)
HI
OK
so I am now stuck on this point, I am a bit new to Lisp macros. I could think of using &rest for this extension, but don’t know how, so I really need your idea on how to get this extension to work.
Thanks a lot.
I assume that you are using some Common Lisp implementation.
That style of argument parsing is not directly supported by the standard lambda lists used by DEFMACRO. You are right in thinking that you will have to parse the arguments yourself (you could use
(test &rest keys-and-forms)to capture TEST, but extracting the :ELSE and :THEN parts would be up to you.I am no super-(Common-)Lisper, but the syntax you are inventing here seems very non-idiomatic. The first hint is that macro lambda lists do not support what you want. Also, there are already standard alternatives that are the same length or shorter in raw characters typed (the typing overhead can be reduced a bit by using a structure editor like paredit in an Emacs).
Common Lisp macros are very powerful code templating engines, but this particular usage makes me think that you are just not quite comfortable with the standard styles and idioms in Common Lisp. No matter which language you are using, it is almost always a good idea to “go with the flow” by adopting the ‘local’ styles and idioms instead of bringing styles and idioms from other languages with which you are more familiar.