我有一个扩展了racket语法的宏,并且在某些时候接受了一系列bog标准球拍表达式。这看起来像这样,相关的语法变量是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?可重用性是一个很大的好处,因为这种&#34;类型的身体&#34;可能存在于多个(类似的)宏中。
一些测试代码:
#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)
答案 0 :(得分:1)
现在重新提出原始问题,我知道(并且可以回答)我想问的问题:如何定义一个只能在某个特定环境中使用的宏(对我来说:在一个方法的主体中) racket class),我如何使用动态绑定变量。在上面的原始代码中:当使用表达式(tweet a)
时,我不仅需要a
的值,还需要some-formal-parameter
的值,该值绑定在代码的上下文中tweet宏被扩展(不是它被定义的地方)。
Chris Jester-Young向我指出了语法参数,它确实似乎解决了动态绑定的问题,而且只能在某些情境中使用&#34;。 Eli Barzilay,Ryan Culpepper和Matthew Flatt的paper帮助我理解了语法参数。
关于我发布的原始示例代码,这是我提出的解决方案:
#lang racket
(require
racket/stxparam
(for-syntax syntax/parse))
(define-syntax-parameter tweet
(lambda (stx)
(raise-syntax-error 'tweet "use of an actor keyword outside of the body of an actor" stx)))
(define-syntax (define-something stx)
(syntax-parse stx
[(_ some-id:id
body:expr ...+)
#'(define some-id
(new
(class object%
(super-new)
(define/public (tick some-formal-parameter)
(syntax-parameterize
([tweet
(syntax-rules ()
[(_ value)
(begin (displayln some-formal-parameter)
(displayln value))])])
body ...)
))))]))
(define-something derp
(define a 'not-derp)
(tweet a))
(send derp tick 'derp)
关注的三个关键点如下:
tweet
宏的定义,只要在syntax-parametrize
语句的上下文之外使用它(它改变了tweet
的定义),它就会抛出一个适当的错误tick
的正文中,我们将tweet
的定义更改为与(_ value)
形式的模式匹配的宏(这是我们提供给的值tweet
)value
,和 some-formal-parameter
的值,无论可能是什么。我不知道这是否是处理这种情况的正确方法,但似乎很好。