It would be better, however, to generate code where the pattern variables become bindings of Scheme variables. Instead of generating code that stuffs the values into an alist, like this code does at the highlighted points:
(make-matcher '((? one) and (? two))) => (lambda (object) (and (pair? object) (let ((left-submatch ((lambda (object) (list (cons 'one object))) (car object))) (right-submatch ((lambda (object) (and (pair? object) (let ((left-submatch ((lambda (object) (and (eqv? object 'and) '())) (car object))) (right-submatch ((lambda (object) (and (pair? object) (let ((left-submatch ((lambda (object) (list (cons 'two object))) (car object))) (right-submatch ((lambda (object) (and (eqv? object '()) '())) (cdr object)))) (and left-submatch right-submatch (append left-submatch right-submatch))))) (cdr object)))) (and left-submatch right-submatch (append left-submatch right-submatch))))) (cdr object)))) (and left-submatch right-submatch (append left-submatch right-submatch)))))We'd generate something more like this:
(make-matcher '((? one) and (? two)) <user code goes here>) => (lambda (object) (and (pair? object) (let ((one (car object)) (tail1 (cdr object))) (and (pair? tail1) (eq? (car tail1) 'and) (let ((tail2 (cdr tail1))) (and (pair? tail2) (let ((two (car tail2))) (and (null? (cdr tail2)) <user code goes here>))))))))This is more challenging for two reasons. First, we need to ensure that the pattern variable names become bound in a scope that encloses the user's code so that free references to pattern variables are correctly captured. In addition, we need to ensure that other “helper” bindings, like
tail1
and tail2
do not capture free references by accident. (That is to say, watch your macro hygiene.) Second, you have to be sure that subpattern bindings are visible to the entire body of the user code. This will throw a monkey wrench into the simple recursive solution.