【问题标题】:Racket Macro How to Pass Ellipses to Helper function?球拍宏如何将省略号传递给辅助函数?
【发布时间】:2012-12-29 01:46:32
【问题描述】:

给定:

(define-syntax (test stx)
  (syntax-case stx ()
    [(_ body ...)
     (with-syntax ([body0 (process-body #'(body ...))])
       #'body0)]))

我应该如何接收助手中的模式和省略号?我什至不确定将 body ... 包裹在 () 内是否正确,但我已经看到它是唯一不会崩溃的东西。

process-body 过程以包含额外 () 的语法结束。我可以尝试将其分解,但我只是想知道正确的方法是什么。

process-body 用一些代码前后包裹了主体模式。而且,与定义类似,我希望能够为宏提供多种形式,而不是一个列表中的所有形式。因此,如果给定 (form1) (form2),其中 form2 是省略号,则流程主体应该 (do-something) (form1) (form2) (do-something-else)。

即,

(define-for-syntax (process-body body-syntax)
  (with-syntax ([stx body-syntax])
    (syntax/loc body-syntax
      (λ (request)
         stx))))

当然,当我定义内联模板时,我有这个工作,我想我可以在这里做,但有时模板变得笨拙,调用帮助器很好。

非常感谢。

作为尝试 dyoo 的第一个示例的编辑,我提供以下内容:

#lang racket

(define-syntax (test2 stx)
  (syntax-case stx ()
    [(_ body ...)
     (with-syntax ([(body0 ...) (process-body2 #'(body ...))])
       #'(begin body0 ...))]))

(define-for-syntax (process-body2 bodies)
  (with-syntax ([(body ...) bodies])
    (syntax/loc bodies
      (λ (request)
         body ...))))

(test2 (print "hi"))

λ:语法错误

【问题讨论】:

  • 如果process-body 打算使用一个语法列表,那么您可能可以执行以下操作:(process-body (syntax->list #'(body ...))),使用syntax->list 将语法对象分段。
  • 不知道更多关于process-body 做什么的信息,这个问题有点不清楚。你能补充更多细节吗?
  • 当然,我编辑了它。让我知道这是否更有意义。我也尝试过(syntax->list),但不确定如何从帮助程序中将列表的 cdr 作为独立语法对象返回。
  • 如果我理解正确的话:可以用begin拼接吗?
  • 这是我不熟悉的拼接。因此,假设 process-body 接收到一个 stx-objects 列表。目前,它只接收一个语法对象并将其作为 (lambda () (something) stx-obj (something-else)) 返回。我想做的基本上是(应用开始stx列表),但这不起作用

标签: macros racket ellipsis


【解决方案1】:

with-syntax 模式的左侧也可以有省略号,因此以下可能:

(define-syntax (test stx)
  (syntax-case stx ()
    [(_ body ...)
     (with-syntax ([(body0 ...) (process-body #'(body ...))])
       #'(begin body0 ...))]))

基本思想是,如果process-body 返回转换后的body 元素,我们可以将它们与begin 一起引入。


您的process-body 定义也可以使用带有省略号的with-syntax。所以你可以这样做:

(define-for-syntax (process-body bodies)
  (with-syntax ([(body ...) bodies])
    (syntax/loc bodies
      (λ (request)
         body ...))))

如果这是process-body的定义,我们应该修改test,因为process-body的结果的形状现在是一个完整的lambda表达式,所以我们可以直接返回它的结果:

(define-syntax (test stx)
  (syntax-case stx ()
    [(_ body ...)
     (process-body (syntax/loc stx (body ...)))]))

作为一个独立的例子:

#lang racket

(define-syntax (test stx)
  (syntax-case stx ()
    [(_ body ...)
     (process-body 
      (syntax/loc stx (body ...)))]))

(define-for-syntax (process-body bodies)
  (with-syntax ([(body ...) bodies])
    (syntax/loc bodies
      (λ (request)
        (printf "before the body\n")
        body ...
        (printf "after the body\n")))))


;; Let's try it:    
(define p 
  (test (displayln "hello") (displayln "world")))

(p 'should-be-a-request)

【讨论】:

  • 好的,成功了。我没有意识到省略号可以像这样进入 with-syntax 的赋值。我试图将它作为 body0 返回,但随后它抱怨模板中没有省略号。
  • 除了,当包装在 lambda 中时,我得到 lambda: bad syntax。因此,如果流程主体是(请参阅问题的结尾进行编辑)。这是由于我认为传入时包裹 #'(body...) 的括号??
  • 基本上,发生的事情是最终返回值是带有 2 括号的 (lambda (lambda (request) ((my-proc)) ,因为原始语法被包裹在括号中以便通过在 #'body ... 作为一个 arg。不过我不确定,大脑开始失灵了 ;)
  • 没问题。让我知道修改后的答案是否有帮助。另请注意 Greg Hendershott 的教程“Fear of Macros”。 greghendershott.com/fear-of-macros
  • 同样的问题,使用您的编辑。 λ:语法错误。 test 和 process-body 形式与您的相同,除了 (syntax/loc body-syntax 现在替换为 (syntax/loc body
猜你喜欢
  • 2013-04-10
  • 2015-01-26
  • 2013-01-16
  • 2016-12-05
  • 2016-04-16
  • 2018-06-21
  • 2019-09-10
  • 1970-01-01
  • 2020-12-19
相关资源
最近更新 更多