Quasiquote
Today I added support for “non-hygenic” macros to my interpreter. I decided to implement the quasiquote feature of Lisp, which is very useful for writing macros, so that I can more comfortably implement more special-forms such as let.
I found an implementation of quasiquote here. My interpreter does not support all the functions it uses so I couldn’t drop it in. It was rather more complicated than I expected and I do not understand exactly how it works. I have written my own version:
(define (expand-quasiquote x)
(if (pair? x)
(if (is? (car x) 'unquote)
(cadr x)
(list 'cons
(expand-quasiquote (car x))
(expand-quasiquote (cdr x))))
(list 'quote x)))
(define-macro (quasiquote x) (expand-quasiquote x))
(Note: is? is a pointer comparison roughly like Scheme’s eqv?)
I haven’t tested thoroughly, but it seems to work just fine. It uses simple recursive strategy: replace atoms by quotation of the atom, replace an unquote form by the raw argument of unquote so it can be evaluated, and replace non-unquoted pairs by the code to cons the car and cdr which are recursively handled. Quasiquotes inside unquotes inside quasiquotes inside … are automatically handled by macro expansion. It doesn’t handle vectors since the interpreter doesn’t have them yet. It is also doesn’t handle unquote-splicing which might complicate matters.
Am I missing something?