我有一个扩展球拍语法的宏,并在某些时候接受一系列沼泽标准球拍表达式 . 看起来像这样,相关的语法变量是 body
:
(syntax-parse stx
[(_ some-id:id
body:expr ...+)
这个宏使用生成的方法生成一个racket类,如下所示:
#'(<class stuff>
(define/public (some-id some-formal-parameter)
body ...)
正如我所说 body
是普通的球拍代码,除了一个可以在体内专门使用的表达式,例如:
(define-syntax-rule (tweet identifier value)
(send this publish-tweet (quote identifier) value))
但这不允许我使用 some-formal-parameter
,因为它没有定义 . 是否有一些正确的方法可以定义可以在主体中专门使用的东西,并且仍然可以在扩展后绑定到上下文中的变量?也许通过splicing syntax class?可重用性是一个很大的好处,因为"type of body"可能存在于多个(相似的)宏中 .
一些测试代码:
#lang racket
(require (for-syntax syntax/parse))
(define-syntax (define-something stx)
(syntax-parse stx
[(_ some-id:id
body:expr ...+)
#'(define some-id
(new
(class object%
(super-new)
(define/public (displ arg)
(displayln arg))
(define/public (tick some-formal-parameter)
body ...))))]))
(define-syntax-rule (tweet value)
(send this displ value))
(define-something derp
(define a 'not-derp)
(tweet a))
(send derp tick 'derp)
1 回答
现在重新提出原始问题,我知道(并且可以回答)我想问的问题:如何定义一个只能在特定上下文中使用的宏(对我来说:在一个球拍类的方法体内) ,以及如何使用动态绑定变量 . 在上面的原始代码中:当使用表达式
(tweet a)
时,我不仅需要a
的值,而且还需要some-formal-parameter
的值,该值在扩展推文宏的代码的上下文中绑定(而不是在其定义的位置) .Chris Jester-Young向我指出了语法参数,它确实似乎解决了动态绑定和"can only be used in certain contexts"的问题 . Eli Barzilay,Ryan Culpepper和Matthew Flatt的paper帮助我理解了语法参数 .
关于我发布的原始示例代码,这是我提出的解决方案:
关注的三个关键点如下 .
由于
tweet
宏的定义,只要在syntax-parametrize
语句的上下文之外使用它(它改变了tweet
的定义),它就会抛出适当的错误 .在我们类的公共方法
tick
的主体中,我们将tweet
的定义更改为与(_ value)
形式的模式匹配的宏(这是我们提供给tweet
的值)推文宏可以扩展为两者都使用绑定值
value
和some-formal-parameter
的值,无论可能是什么 .我不知道这是否是处理这种情况的正确方法,但似乎很好 .