我正在使用 Dr. Racket,版本 5.3.1。我正在尝试使用宏步进器功能,但遇到了“嵌套”宏的问题。(通过“嵌套”宏,我的意思是扩展为包含更多(使用定义的)宏的形式的宏。我不知道这是否是正确的术语)。宏步进器只扩展这些宏一次,然后就不再费心继续扩展了。
例如,我在 Dr. Racket 定义区域输入以下内容:
#lang racket
(define-syntax foo
(syntax-rules ()
((foo a) 1)
((foo a stuff ...) (+ 1 (foo stuff ...)))))
(foo a b c d e)
正如预期的那样,运行它会返回 5。(expand '(foo a b c d e))
此外,在 Interactions 窗口中键入会产生 syntax '(#%app + '1 (#%app + '1 (#%app + '1 (#%app + '1 '1))))
,也如预期的那样。但是,进入宏步进器(带有标准宏隐藏)并按下End
按钮,我只看到(+ 1 (foo b c d e))
. 如果我禁用宏隐藏,我会得到预期的结果,但也会有很多我不想看到的线路噪音。
这是一个错误,还是预期的行为?我发誓 Racket 博士以前没有这样的行为……
我实际上在一个月前提交了一份关于此的错误报告(http://bugs.racket-lang.org/query/?cmd=view&pr=13203),但后来我开始重新考虑这是否是一个错误,所以我决定在这里问。
PS - 关于此的其他随机注释:
它似乎取决于嵌套宏是否是扩展形式的最外层表达式。例如,如果我定义(除了 foo):
(define-syntax bar
(syntax-rules ()
((bar xs ...) (foo xs ...))))
(define-syntax baz
(syntax-rules ()
((baz xs ...) (bar xs ...))))
(baz a b c d e)
然后宏步进器向我显示(baz a b c d e)
扩展为(bar a b c d e)
to (foo a b c d e)
to (+ 1 (foo b c d e))
,但随后停止。
前面的示例可能会让您认为它与扩展为自身的宏有关,但事实并非如此。例如,如果我重新定义 foo 如下:
(define-syntax foo
(syntax-rules ()
((foo a) 1)
((foo a stuff ...) (+ 1 (blah stuff ...)))))
和
(define-syntax blah
(syntax-rules ()
((blah xs ...) 10)))
然后(foo a b c d e)
扩展到(+ 1 (blah b c d e))
然后停止。