我想将特殊变量注入宏中以进行编译时绑定。
因此,例如,以下形式:
(define-route (my/route)
(some-proc @@request)
(some-other-proc @@request))
应扩展为:
(some-code)
...
(lambda (request)
...
(some-proc request)
(some-other-proc request))
其中请求绑定到生成的代码中的请求,在调用者指定的所有位置。
我不确定如何做到最好。这是一种更常见的模式,球拍宏提供了做的能力,还是我必须手动完成?
如果是这样,我是否应该递归遍历主体模式,寻找符合'@@ request的符号,然后替换它们?我注意到syntax-> list不是以这种方式递归的,即
(syntax->list #'(printf "first: ~a\" (get-var (other-proc)))
是3个语法对象而不是4个,第三个syntax-obj是2个。所以我假设我需要在这里手动重复,但也许有更好的方法来做到这一点?
感谢您的帮助。
答案 0 :(得分:4)
也许使用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)
语法参数化在@@request
的词汇上下文中重新使用define-route
,以便它返回request
被lambda
约束的define-route
。如果在@@request
的上下文之外使用,它将尝试提出合理的错误消息。
(你可以按照你最初计划的方式执行此操作,以递归方式遍历语法对象的结构并选择{{1}}元素。这比你需要的工作更多除非要求真的不寻常。)