2

I'm trying to write a pattern matching macro. I haven't got very far but I'm already confused. My test code is as follows

#!r6rs

(import (for (rnrs base (6)) run expand)
        (for (rnrs syntax-case (6)) expand)
        (rnrs io simple (6)))

(define-syntax matcher
  (lambda (stx)

    (define (parse-clauses c)
      #'x)

    (syntax-case stx ()
      ((_ c ...)
       (with-syntax ((body (parse-clauses #'(c ...))))
         #'(lambda (x) body))))))

(write ((matcher) '(1 2 3))) (newline)

Executing this produces the output (1 2 3).

To be honest I wrote this code in the expectation that it would fail. I thought the syntax returned from parse-clauses refers to an undefined symbol x. But it seems that #'x returned from parse-clauses does reference the parameter x in the lambda expression. I've no idea why.

This slight variation has me even more confused.

#!r6rs

(import (for (rnrs base (6)) run expand)
        (for (rnrs syntax-case (6)) expand)
        (rnrs io simple (6)))

(define-syntax matcher
  (lambda (stx)

    (define (parse-clauses c)
      (let ((x 1))
        #'x))

    (syntax-case stx ()
      ((_ c ...)
       (with-syntax ((body (parse-clauses #'(c ...))))
         #'(lambda (x) body))))))

(write ((matcher) '(1 2 3))) (newline)

This produces the error x: identifier used out of context in: x. This error I understand, x is bound locally in parse-clauses, but I'm using the reference outside of that scope so I get an error.

I guess what I'm saying is that the second example shows that the lexical context matters but in the first example there is no lexical binding for x so how come it ends up referring to an unrelated binding?

I hope that's not too confused, any explanations welcome.

I'm using Racket 5.3.6.

john
  • 85,011
  • 4
  • 57
  • 81

1 Answers1

0

The x refers to the lambda argument because they're both introduced by the same macro expansion step -- the macro system only distinguishes identifiers introduced by different steps (if this macro expands into another macro that introduces another x, it will be a different one).

I think the second error is because x is bound as a compile-time variable (parse-clauses is a compile-time function) and it somehow interferes with the x in the lambda.

hzap
  • 1,103
  • 7
  • 9