为什么Clojure中的宏展开不会展开嵌套表单?

3

我不明白如何获得完整的宏展开。

使用以下代码:

(when true (when true true))

我希望能够获得完整的宏展开。
(if true (do (if true (do true)))

但我无法

我理解macroexpansion-1将解析第一级扩展:

(macroexpand-1 '(when true (when true true)))

(if true (do (when true true)))

但是为什么当我再次调用macroexpand-1(这就是macroexpand应该做的事情)时:

(macroexpand-1 '(if true (do (when true true))))

我得到了完全相同的结果。
(if true (do (when true true)))

我原本期望进行完整的宏展开。
宏展开仅适用于顶层表达式吗?
我知道在 clojure.walk 命名空间中有一个 expand-all 函数,因此我认为 macroexpand 不能用于嵌套结构。我对吗?
1个回答

7

你说得对。

参见 https://clojuredocs.org/clojure.core/macroexpand

其中写道:

注意,macroexpand-1和macroexpand都不会在子表达式中展开宏。

事实上,macroexpand-all会进行递归扩展:

> (clojure.walk/macroexpand-all '(when true (when true true))) 
(if true (do (if true (do true))))

请参阅https://clojuredocs.org/clojure.walk/macroexpand-all,其中说明:

递归地执行表单中所有可能的宏扩展。

您的示例为:

(macroexpand-1 '(if true (do (when true true))))

这段文字可能会让你感到困惑,但它确实如文档所述:

(macroexpand-1 form) 如果form代表一个宏形式,则返回它的扩展形式,否则返回form。

因此,由于'if'不是宏,它只返回if,而不进入子表单...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接