If you look at the literature there are numerous examples of extensible macros. Often this is done for rule-based systems, which also involves matching or unification. Typically one wants to define these rules individually, update them individually, etc.<p>One needs a registry, an interning function and a driving function. Below is just an example:<p><pre><code> (defvar *patterns* (make-hash-table))
(defparameter *pattern-names* nil)
(defun intern-pattern (name if-pattern then-pattern)
(setf *pattern-names*
(append *pattern-names* (list name)))
(setf (gethash name *patterns*)
(list (compile nil `(lambda (pat)
,if-pattern))
(compile nil `(lambda (pat expr then else)
(declare (ignorable pat expr then else))
,then-pattern))))
name)
(defmacro if-match (pat expr then else)
(loop for name in *pattern-names*
for (if-part then-part) = (gethash name *patterns*)
when (funcall if-part pat)
do (return (funcall then-part pat expr then else))))
(intern-pattern 'variable
'(and pat (symbolp pat))
'`(let ((,pat ,expr)) ,then))
(intern-pattern 'literal-atom
'(atom pat)
'`(if (equalp ',pat ,expr) ,then ,else))
(intern-pattern 'cons
'(eq 'cons (car pat))
'(destructuring-bind (_ p-car p-cdr) pat
(declare (ignore _))
(let ((tmp (gensym)))
`(let ((,tmp ,expr))
(if (consp ,tmp)
(if-match ,p-car
(car ,tmp)
(if-match ,p-cdr
(cdr ,tmp)
,then
,else)
,else)
,else)))))
</code></pre>
Writing the macro DEFPATTERN is then trivial...<p>I help maintain an old Lisp-based web server, which was written in the mid-90s on the Symbolics Lisp Machine. It literally has zillions of these registry/intern/machinery/defining-macro combinations...<p>It's just: one has to program those. But it has been done many many many times.