I learned that it is easy to define a small macro in scheme by syntax-rules
.
Is it possible to define a syntax-rules
macro which will return a list can be read by defmacro
in Common Lisp?
Which might work like this:
(defmacro and (&rest rest)
(syntax-rules (rest) ()
((_) t)
((_ x) x
((_ x y) (if x (if y y nil) nil))
((_ x y ...) (if x (and y ...) nil))))
Tim Bradshaw's destructuring-match
is intended to make this kind of pattern matching easy in macros: it is a combination of case
and destructuring-bind
, so the key of each clause has the syntax of a destructuring lambda list. There are several other pattern matching systems for CL, but this one explicitly is aimed at writing macros: it's not a general data structure matching tool, just a generalised version of destructuring-bind
.
It comes with a little example macro (itself written using destructuring-match
as well as expanding into something which uses destructuring-match
!) called define-matching-macro
, in which you can write a version of and
, here called et
. I think the following two macros are correct but I have not thought much about them.
(define-matching-macro et
"This is meant to be AND"
((_) 't)
((_ x) x)
((_ x . more ) `(if ,x (et ,@more) nil)))
You can alternatively just use destructuring-match
in an ordinary defmacro
macro. Here I am not using &whole
to get the whole form so we don't have to bother with the car
of the form:
(defmacro et (&rest forms)
"This is also meant to be AND"
(destructuring-match forms
(() 't)
((x) x)
((x . more) `(if ,x (et ,@more) nil))))
Notes:
destructuring-match
uses symbols whose name is "_"
as blanks the same way Scheme does, so you don't need to declare them ignored, they are all distinct from each other, and in fact you may not refer to them in the body of the clause; but it does not do Scheme's x ...
thing at all, so you just need to use dotted lambda lists or &rest
or whatever you prefer;(if x x nil)
, as well as being redundant (it's just x
) may evaluate x
twice, which is unsafe.