Макрос ракетки, который определяет несколько форм верхнего уровня?
Я определил параметры синтаксиса с идентичными определениями, за исключением их имени, поэтому решил написать макрос, чтобы сделать это проще:
(define-syntax (test-case-parameter stx)
(syntax-parse stx
[(_ parameter:id)
#'(define-syntax-parameter parameter
(lambda (stx)
(raise-syntax-error stx "Can only be used inside test-case.")))]))
(test-case-parameter a)
(test-case-parameter b)
(test-case-parameter c)
Однако вместо того, чтобы повторять имя макроса, я хотел бы просто написать:
(test-case-parameter a b c)
Но я не вижу, как это сделать, используя обычный синтаксис эллипсов, потому что мне нужно было бы обернуть все в begin
что создаст новую область видимости, и я хочу, чтобы все параметры синтаксиса были такими, как если бы я написал их для каждого верхнего уровня. Как правильно это сделать?
2 ответа
Ответ заключается в использовании begin
, begin
странно, потому что поведение на верхнем уровне отличается от поведения в контексте выражения. На верхнем уровне у него есть тот тип поведения сплайсинга, который вы хотели бы использовать для этого макроса, но в контексте выражения он имеет поведение области видимости, на которое вы ссылаетесь.
Таким образом, вы можете определить свой макрос следующим образом:
#lang racket
(require racket/stxparam (for-syntax syntax/parse))
(define-syntax (define-test-case-parameters stx)
(syntax-parse stx
[(_ parameter:id ...)
#'(begin
(define-syntax-parameter parameter
(lambda (stx)
(raise-syntax-error stx "Can only be used inside test-case.")))
...)]))
(define-test-case-parameters a b c)
Вы можете увидеть, как begin
работы по сращиванию на высшем уровне в Macro Stepper в DrRacket:
Создайте новый макрос, который принимает несколько идентификаторов, и пусть он расширяется до последовательности использования вашей версии, которая использует один идентификатор.
#lang racket
(require (for-syntax syntax/parse)
racket/stxparam)
(define-syntax (test-case-parameter-helper stx)
(syntax-parse stx
[(_test-case-parameter-helper parameter:id)
(syntax/loc stx
(define-syntax-parameter parameter
(lambda (stx)
(raise-syntax-error stx "Can only be used inside test-case."))))]))
(define-syntax (test-case-parameter stx)
(syntax-parse stx
[(_test-case-parameter parameter:id ...)
(syntax/loc stx
(begin
(test-case-parameter-helper parameter)
...))]))
(test-case-parameter a b c)