我在Clojure中遇到了一个与defmacro有关的奇怪问题,我有以下代码:
(defmacro ttt
([] (ttt 1))
([a] (ttt a 2))
([a b] (ttt a b 3))
([a b c] `(println ~a ~b ~c)))
我跑的时候用的是(ttt)
,它应该变成(println 1 2 3)
,并打印出"1 2 3",但我得到的是
and I run with (ttt)
, it suppose to become (println 1 2 3)
, and print "1 2 3", but what I got is
ArityException Wrong number of args (-1) passed to: t1$ttt clojure.lang.Compiler.macroexpand1 (Compiler.java:6473)
经过一些调查,我了解到应该这样写
(defmacro ttt
([] `(ttt 1))
([a] `(ttt ~a 2))
([a b] `(ttt ~a ~b 3))
([a b c] `(println ~a ~b ~c)))
但为什么第一个版本失败了?而且args
太奇怪了,不容易理解,-1
又是从哪里来的呢?
macroexpand
通过反复调用macroexpand-1
来计算不动点,但是macroexpand
和macroexpand-1
都没有递归地调用自身(除非你的宏这样做)。参见https://dev59.com/SZvga4cB1Zd3GeqP2Xij。 - coredumpmacroexpand
确实以递归方式调用自身。也许你是在说macroexpand
不会进入子表单?这是正确的,但当然编译器会进入子表单,这将根据需要触发新的 macroexpand 调用。 - A. Webb