我正在使用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))
会产生语法'(#%app + '1 (#%app + '1 (#%app + '1 (#%app + '1 '1))))
,也会如预期的那样。但是,进入Macro Stepper(标准宏隐藏)并按下End
按钮,我只看到(+ 1 (foo b c d e))
。如果我禁用宏隐藏,我会得到预期的结果,但也有很多我不想看到的线路噪音。
这是一个错误,还是预期的行为?我发誓Dret博士不习惯这样......
我实际上在一个月前提交了一份关于此问题的错误报告(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)
到(foo a b c d e)
到(+ 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))
然后停止。
答案 0 :(得分:0)
我不确定这是不是一个bug,虽然扩展代码中的foo与原来的foo不同,所以我倾向于认为这就是令人困惑的事情。
默认情况下,宏步进器会尝试简化扩展宏,以仅显示模块中定义的宏,以及字符串所需的文件(即“项目”中的文件)。这个功能似乎正在抛弃它。
解决此问题的一种方法(至少在小文件中)是禁用此功能。要执行此操作,请转到窗口左下角的Macro hiding:
,点击下拉菜单,然后选择Disable
。
Macro hiding:
- > Disable
从那里,您应该看到模块的整个扩展,包括foo
的扩展。