3

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

因此,例如,以下形式:

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

应扩展为:

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

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

我不知道如何最好地去做。这是球拍宏提供执行能力的更常见模式,还是我必须手动执行?

如果是这样,我是否应该递归循环遍历主体模式,寻找任何匹配 '@@request 的符号然后替换它们?我注意到 syntax->list 不是以这种方式递归的,即

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

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

谢谢你的帮助。

4

1 回答 1

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)

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

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

于 2013-01-14T23:26:58.453 回答