3

我刚刚开始深入研究 Racket 宏,并试图制作一个简洁的简单宏定义宏。我想扩展这样的表达式:

(macro id
    (param) replacement1
    (params ...) replacement2)

变成这样:

(define-syntax id
    (syntax-rules ()
        ((id param) replacement1)
        ((id params ...) replacement2)))

所以原始表达式的 cddr 变成了表达式对(用于语法规则主体),并将 id 插入到每对表达式的 car 中。

当仅使用语法规则提供的模式匹配时,我在递归思考时遇到了麻烦(我一直想像操作普通列表一样操作表达式)。我应该使用什么样的模式?或者,我可以以某种方式将其作为普通列表进行操作,然后取消引用结果以用于扩展吗?

非常感谢

编辑 - 暂定解决方案,由 Taymon 的回答提供信息

我在这里的部分好奇心是关于摆脱那些配对括号。我研究了语法案例,但有点困惑,所以尝试纯粹使用模式匹配子语言来做。我最终使用 Taymon 的宏和另一个宏来“配对”给定的模板(它的行为有点像累加器函数):

(define-syntax-rule (macro-aux id ((param ...) expr) ...)
  (define-syntax id
    (syntax-rules ()
      ((id param ...) expr)
      ...)))

(define-syntax pairize
  (syntax-rules ()
   ((pairize id (pairs ...) p b) (macro-aux id pairs ... (p b)))
   ((pairize id (pairs ...) p b rest ...) (pairize id (pairs ... (p b)) rest ...))))

(define-syntax macro
  (syntax-rules ()
    ((macro id tpl-expr ...) (pairize id () tpl-expr ...))))
4

2 回答 2

7

可以构建一个宏扩展器,将语法表达式作为常规 Racket 数据进行操作。但是,在这种情况下,这并不是必需的。

我建议的一件事是稍微更改您的语法,以便将每个模式替换对括在括号中。像这样:

(macro id
  [(param) replacement1]
  [(params ...) replacement2])

完成后,您可以使用常规模式匹配宏。这是我的看法:

(define-syntax-rule (macro id [(param ...) replacement] ...)
  (define-syntax id
    (syntax-rules ()
      [(id param ...) replacement] ...)))
于 2012-03-25T14:24:15.780 回答
2

Taymon 是对的,但也可以使用省略号来做到这一点,而无需将模式替换对包裹在括号中,使用~seqfrom syntax/parse

(require syntax/parse/define)
(define-simple-macro (macro id (~seq (param ...) replacement) ...)
  (define-syntax id
    (syntax-rules ()
      [(id param ...) replacement] ...)))

可以像您最初想要的那样使用:

(macro id
  (param) replacement1
  (params ...) replacement2)
于 2015-11-05T03:30:11.087 回答