Macros 如何在其他宏中展开宏';s范围(尝试调试宏)

Macros 如何在其他宏中展开宏';s范围(尝试调试宏),macros,clojure,Macros,Clojure,下面是我能举的最简单的例子: (defmacro printer [& forms] `(println ~@forms)) (defmacro adder [s] `(inc ~s)) 它们可以按预期使用: (printer "haha") => "haha" (adder 1) => 2 我可以宏展开查看宏的功能: (macroexpand '(printer 1)) => (clojure.core/println 1) (macroexpand

下面是我能举的最简单的例子:

(defmacro printer [& forms]
  `(println ~@forms))

(defmacro adder [s]
  `(inc ~s))
它们可以按预期使用:

(printer "haha")
=> "haha"

(adder 1)
=> 2
我可以
宏展开
查看宏的功能:

(macroexpand '(printer 1))
=> (clojure.core/println 1)

(macroexpand '(adder 1))
=> (clojure.core/inc 1)
但当它们嵌套时,我得不到我想要的:

(macroexpand '(printer (adder 1)))
=> (clojure.core.println (adder 1))
我希望得到一份工作

=> (clojure.core.println (clojure.core/inc 1))
有什么方法可以扩展嵌套宏吗? 这对我调试一个特定的bug会有很大帮助。

你在找什么


谢谢你接受我的回答,我很高兴它有帮助。我忘了补充一点,如果您想完全扩展编译器看到的内容,可以利用clojure分析器的强大功能:

(use '[clojure.tools.analyzer.passes.jvm.emit-form :only [emit-form emit-hygienic-form]]
     '[clojure.tools.analyzer.jvm :only [analyze]])

(emit-form (analyze '(printer (adder 1))))

(emit-hygienic-form (analyze '(printer (adder 1))))
上述两种方法给出的结果与
macroexpand all
几乎相同,但应涵盖
macroexpand all
可能无法完全工作的情况。在您的示例中,它将
inc
扩展到
inc
定义中的内联函数。另外,
emit-form
在检查阴影时非常有用:

(emit-form (analyze '(let [a 1 a a] a)))
;=> (let* [a 1 a a] a)

(emit-hygienic-form (analyze '(let [a 1 a a] a)))
;=> (let* [a__#0 1 a__#1 a__#0] a__#1)

最后,
macroexpand-1
macroexpand all
emit form
emit-form
都对调试clojure宏很有用。

非常感谢!多亏了你,我调试了我的bug:)干杯=)这可能会在将来派上用场。
(emit-form (analyze '(let [a 1 a a] a)))
;=> (let* [a 1 a a] a)

(emit-hygienic-form (analyze '(let [a 1 a a] a)))
;=> (let* [a__#0 1 a__#1 a__#0] a__#1)