I am currently porting Alex Shinn's canonical implementation of match for Scheme, which is used by almost all Scheme implementations, to another Lisp.

I've run into a total wall with match-letrec . In the simplified version of his implementation, it's defined as follows:

(define-syntax match-let (syntax-rules () ((_ ((pat expr)) . body) (match expr (pat . body))) ((_ ((pat expr) ...) . body) (match (list expr ...) ((pat ...) . body))) ((_ loop . rest) (match-named-let loop () . rest)) )) (define-syntax match-letrec (syntax-rules () ((_ vars . body) (match-letrec-helper () vars . body)))) (define-syntax match-letrec-helper (syntax-rules () ((_ ((pat expr var) ...) () . body) (letrec ((var expr) ...) (match-let ((pat var) ...) . body))) ((_ (v ...) ((pat expr) . rest) . body) (match-letrec-helper (v ... (pat expr tmp)) rest . body)) ))

Here's an example of how it looks when in use (Guile 1.8):

(match-letrec (((x y) (list 1 (lambda () (list a x)))) ((a b) (list 2 (lambda () (list x a))))) (append (y) (b)) => (2 1 1 2)

I'm having great difficulty understanding how this actually works. When I expand this by hand as far as match , I get the following code (with automatic symbols indicated by #{g...} ):

(letrec ((#{g1} (list 1 (lambda () (list a x)))) (#{g2} (list 2 (lambda () (list x a))))) (match (list #{g1} #{g2}) (((x y) (a b)) (append (y) (b))))

The automatic symbols are generated by the tmp substitution in the second rule of match-letrec-helper . This expansion means that the lambda expressions are evaluated before x and a are bound, and therefore cannot capture them.

Can someone please explain how this syntax is supposed to be correctly expanded? What have I missed?