对于我来说,clojure宏是一个难点,这是一个从"Pratical Clojure"中获取的宏观示例:
(defmacro triple-do [form]
(list 'do form form form))
user=> (triple-do (println "test"))
test
test
test
nil
Run Code Online (Sandbox Code Playgroud)
这个三合一效果很好而且我认为以下版本应该可以工作但不能
(defmacro triple-do [form]
(do form form form))
user=> (triple-do (println "test"))
test
nil
Run Code Online (Sandbox Code Playgroud)
为什么它只打印一次?
以下让我非常困惑
(defmacro test-macro [form] (do form (println "hard code test")))
user=> (test-macro (println "hello"))
hard code test
nil
Run Code Online (Sandbox Code Playgroud)
为什么"你好"没有在控制台中显示?
宏是一个函数,它返回一个Clojure s-expression,然后编译,或者如果宏返回一个宏,则再次展开.这个替换过程递归重复,直到没有宏保留,然后评估最终代码.与最终生成的代码运行的内容相比,有助于仔细考虑宏扩展时的运行情况.
macroexpand-1通过向您展示宏扩展的内容,该功能非常有用:
user> (macroexpand-1 '(test-macro (println "hello")))
hard code test
nil
Run Code Online (Sandbox Code Playgroud)
从中您可以看到在宏扩展时发生了print语句.如果在执行之前添加语法引用,则宏可能更有意义.
user> (defmacro test-macro [form] `(do ~form (println "hard code test")))
#'user/test-macro
user> (macroexpand-1 '(test-macro (println "hello")))
(do (println "hello") (clojure.core/println "hard code test"))
Run Code Online (Sandbox Code Playgroud)
在这种情况下,打印在宏完成扩展后运行.