I was hacking some Scheme code (about which a post will be forthcoming) recently and got to thinking that syntax-rules was nice. Really, really, nice. For those unfamiliar with it, both Scheme and Common Lisp include support for macros, which are, basically, readtime code transformations. These transformations are not unlike those done with #define in C and C++, in that they happen before the code is ever run or compiled, but are much more powerful. Common Lisp macros are functions that accept a form has input and produce another form as output to be evaluated. Scheme macros, on the other hand, are usually defined with syntax-rules, which allows the input to be transformed according to rules. In this sense, the Scheme macro system is similar to Awk or XSLT. From all I can tell, the systems are equal in terms of raw power. However, there are cases when the Scheme version is simpler or more concise. So, I consulted google. It turns out that Dorai Sitaram has implemented Scheme macros in Common Lisp. It is an interesting little library, to say the least. I thought one comment the author made was odd, though: "The ellipsis is represented by `...' in Scheme. This Common Lisp implementation uses `***' instead, since `...' is disallowed by Common Lisp's identifier conventions." This is almost true. If you use ... directly at the top level, you will indeed get an error. However, the spec does provide for using odd characters in symbols using the | syntax. So, this fails:
(let ((... 1)) ...)
but
(let ((|...| 1)) |...|)
works. "But wait a minute," you may say, "|...| isn't the same as ...". Well, yes, it is. In the eq, eql, and equal senses of the word, ... is |...|. Perhaps it would be more precise to say that ... is the print name for both appearances of the form...which is what matters.
The nice point for Scheme is that, of course, you can use either macro system with no extra dependencies (assuming, of course, R5+RS compliance). However, I cannot say which system I like better. syntax-rules can be kind of nice, particularly for comparably simple macros that involve symbols as keywords (i.e. something like (do ... with foo)), but for anything more complex, the rules get so tangled that you are probably better of doing things the Common Lisp way (which is, I'm sure, why Scheme includes support for low level macros like that).