gpt4 book ai didi

macros - Racket - 将特殊变量注入(inject)宏代码

转载 作者:行者123 更新时间:2023-12-02 02:21:58 26 4
gpt4 key购买 nike

我想将特殊变量注入(inject)宏以进行编译时绑定(bind)。

例如,以下形式:

(define-route (my/route)
(some-proc @@request)
(some-other-proc @@request))

应扩展为:

(some-code)
...
(lambda (request)
...
(some-proc request)
(some-other-proc request))

其中请求在调用者指定的所有位置绑定(bind)到生成代码中的请求。

我不知道如何最好地解决这个问题。这是 Racket 宏提供的更常见的模式,还是我必须手动执行?

如果是这样,我是否应该递归循环主体模式,查找与“@@request”匹配的任何符号,然后替换它们?我注意到语法->列表不是以这种方式递归的,即

(syntax->list #'(printf "first: ~a\" (get-var (other-proc)))

是3个语法对象而不是4个,第三个syntax-obj又是2个。所以我假设我需要在这里手动重复,但也许有更好的方法来做到这一点?

感谢您的帮助。

最佳答案

也许使用 syntax-parameterize (及其变体 splicing-syntax-parameterize )应该可以解决问题吗?当您想要拥有类似关键字的内容,并且宏需要根据上下文重新连接关键字的含义时,它是一个标准工具。

它看起来像这样:

#lang racket/base

(require racket/stxparam
racket/splicing
(for-syntax syntax/parse racket/base))

(define-syntax-parameter @@request
(lambda (stx)
(raise-syntax-error #f "Use outside of a define-route" stx)))

(define-syntax (define-route stx)
(syntax-parse stx
[(_ (name:id) body:expr ...)
(syntax/loc stx
(begin
(printf "blah blah blah\n")

(define name
(lambda (request)
(splicing-syntax-parameterize ([@@request
(make-rename-transformer #'request)])
body ...)))))]))

;; example
(define (f r)
(printf "f sees: ~s\n" r))

(define-route (my/route)
(f @@request))

(my/route 42)

语法参数化在define-route的词法上下文中重新连接了@@request的使用,以便它引用回requestlambda 约束。如果在 define-route 的上下文之外使用,它会尝试引发合理的错误消息。

(您可以按照您最初计划的方式执行此操作,递归地遍历语法对象的结构并挑选出@@request元素。这只是更多工作超出您需要做的工作,除非要求确实不寻常。)

关于macros - Racket - 将特殊变量注入(inject)宏代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14328396/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com