Macros 如何在clojure中扩展宏?

Macros 如何在clojure中扩展宏?,macros,clojure,expand,Macros,Clojure,Expand,在《编程Clojure》(Stuart)一书中,当读到宏是如何扩展的时,我感到困惑 user=> (defmacro chain ([x form] (list '. x form)) ([x form & more] (concat (list 'chain (list '. x form)) more))) #'user/chain 上述宏可以展开为: user=> (macroexpand '(chain a b c)) (.

在《编程Clojure》(Stuart)一书中,当读到宏是如何扩展的时,我感到困惑

user=> (defmacro chain
          ([x form] (list '. x form))
          ([x form & more] (concat (list 'chain (list '. x form)) more)))
#'user/chain
上述宏可以展开为:

user=> (macroexpand '(chain a b c))
(. (. a b) c)
但以下仅扩展到第一级:

user=> (macroexpand '(and a b c))
(let* [and__3822__auto__ a]
     (if and__3822__auto__ (clojure.core/and b c) and__3822__auto__))
宏源:

user=> (source and)
(defmacro and([] true)
    ([x] x)
    ([x & next]
    `(let [and# ~x]
          (if and# (and ~@next) and#))))
为什么宏一直在扩展,而没有?为什么不扩展为以下内容:

user=> (macroexpand '(chain a b c d))
(. (chain a b c) d)

macroexpand
反复展开最外层的表单,直到得到非宏结果。如果只想查看宏扩展的单个阶段的输出,请使用
macroexpand-1


所以区别在于,
chain
的递归调用是第一位的,而
的递归调用不是第一位的。

对我来说,amalloy的回答直接回答了你的问题。然而,如果你的问题被掩盖了,你会想知道如何展示事物的完全宏观扩展形式,我会告诉你的方向是。使用相同的示例,现在使用macroexpand all:

user=> (macroexpand-all '(and a b c))
(let* [and__3546__auto__ a]
  (if and__3546__auto__
    (let* [and__3546__auto__ b]
      (if and__3546__auto__ c and__3546__auto__))
    and__3546__auto__))
所有宏都已展开。还要注意,对于第一个示例,它的行为与
宏扩展
相同(基于amalloy给出的原因):

user=> (macroexpand-all '(chain a b c))
(. (. a b) c)