лексическая область видимости и синтаксический регистр

Я пытаюсь написать макрос сопоставления с образцом. Я не продвинулся очень далеко, но я уже запутался. Мой тестовый код выглядит следующим образом

#!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)

Выполнение этого приводит к выводу (1 2 3).

Честно говоря, я написал этот код в расчете на то, что он не сработает. Я думал, что синтаксис, возвращенный из parse-clauses, относится к неопределенному символу x. Но похоже, что #'x, возвращаемый из parse-clauses, ссылается на параметр x в лямбда-выражении. Я понятия не имею, почему.

Эта небольшая вариация сбила меня с толку еще больше.

#!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)

Это приводит к ошибке x: identifier used out of context in: x. Я понимаю эту ошибку, x локально привязан к parse-clauses, но я использую ссылку за пределами этой области, поэтому получаю сообщение об ошибке.

Я думаю, что я хочу сказать, что второй пример показывает, что лексический контекст имеет значение, но в первом примере нет лексической привязки для x, так почему же он в конечном итоге ссылается на несвязанную привязку?

Я надеюсь, что это не слишком запутано, любые объяснения приветствуются.

Я использую Racket 5.3.6.


person john    schedule 23.11.2013    source источник


Ответы (1)


x относится к лямбда-аргументу, потому что они оба вводятся на одном и том же шаге расширения макроса — система макросов различает только идентификаторы, введенные на разных шагах (если этот макрос расширяется в другой макрос, который вводит другой x, он будет другим). ).

Я думаю, что вторая ошибка связана с тем, что x связана как переменная времени компиляции (parse-clauses — это функция времени компиляции), и она каким-то образом мешает x в лямбда-выражении.

person hzap    schedule 23.11.2013