定义多个顶级表单的球拍宏?
Racket macro that defines multiple top-level forms?
我发现我自己定义的语法参数除了名称之外都具有相同的定义,所以我决定编写一个宏来简化这个过程:
(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
中,这将创建一个新的范围,而且我想要所有语法参数就好像我把它们都写在了顶层。实现此目标的正确方法是什么?
制作一个接受多个标识符的新宏,并让它扩展为使用单个标识符的版本的一系列用法。
#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)
答案是使用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)
你可以在DrRacket的Macro Stepper中看到begin
顶层拼接是如何工作的:
我发现我自己定义的语法参数除了名称之外都具有相同的定义,所以我决定编写一个宏来简化这个过程:
(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
中,这将创建一个新的范围,而且我想要所有语法参数就好像我把它们都写在了顶层。实现此目标的正确方法是什么?
制作一个接受多个标识符的新宏,并让它扩展为使用单个标识符的版本的一系列用法。
#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)
答案是使用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)
你可以在DrRacket的Macro Stepper中看到begin
顶层拼接是如何工作的: