Я пытаюсь написать макрос сопоставления с образцом. Я не продвинулся очень далеко, но я уже запутался. Мой тестовый код выглядит следующим образом
#!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.