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

标签 macros racket

我想将特殊变量注入(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/

相关文章:

c++ - 在 C++ 的宏中包装方法

functional-programming - 忽略 Racket 中的多个返回值

scheme - 数据定义 DrRacket?

用于更复杂功能的 C 宏

c++ - 如何在我的命名空间中使用 LoadString 宏?

macros - 在 Racket 中,我可以重新定义形式 `if` 并让其他派生形式自动遵循其新语义吗?

dictionary - Racket : (map #(procedure) (list)) 中的 Clojure 等效项

scheme - 如何解决此错误 "reference to an identifier before its definition: with"

c++ - 参数有几行的宏​​函数?

c++ - 一个宏定义调用中的对象及其类定义