Clojure 为什么宏扩展不打印defmacro的结果?
我是Clojure的新手,目前正在尝试使用Clojure 为什么宏扩展不打印defmacro的结果?,clojure,Clojure,我是Clojure的新手,目前正在尝试使用defmacro和macroexpand调用一个简单的宏 (ns tutorial.core (:gen-class)) ; namespace (defn -main [& args] (defmacro Simple [] (println "Hello")) (macroexpand '(Simple)) ) 我错过了什么吗?程序运行似乎没有任何问题,但结果并没
defmacro
和macroexpand
调用一个简单的宏
(ns tutorial.core
(:gen-class)) ; namespace
(defn -main [& args]
(defmacro Simple [] (println "Hello"))
(macroexpand '(Simple))
)
我错过了什么吗?程序运行似乎没有任何问题,但结果并没有如预期的那样
我希望结果打印为Hello
,但此脚本不会产生任何输出结果。前言:
关于(IMHO)的概述,请参见过去的问题
答复: 您不应该在
main
函数中定义宏。试试这个:
(ns demo.core)
(defmacro happy
[]
`(println "I'm happy!")) ; *** notice the backtick! ***
(defn -main [& args]
(println :expanded (macroexpand '(happy)))
(happy)
)
启动repl:
~/expr/demo > lein repl
demo.core=> (macroexpand '(happy))
;=> (clojure.core/println "I'm happy!")
我们看到它是有效的。尝试从命令行运行:
~/expr/demo > lein run
:expanded (happy) ; <= ***** OOOPS! *****
I'm happy!
解释是,语法引号将完全限定Varhappy
=>demo.core/happy
(由于该语法引号,您可以在happy
宏内部的println
Var上看到相同的效果)。这允许宏扩展正常工作。与单个报价相比:
(defn -main [& args]
(println :expanded (macroexpand '(demo.core/happy)))
(happy))
~/expr/demo > lein run
:expanded (clojure.core/println I'm happy!)
I'm happy!
这种行为的原因是,在REPL中,我们从提示中看到我们在demo.core
命名空间中,因此happy
被解析为demo.core/happy
。但是,当我们在运行时使用时,请注意:
(defn -main [& args]
(println *ns*)
(println (ns-name *ns*)))
结果:
~/expr/demo > lein run
*ns* => #object[clojure.lang.Namespace 0xb625b00 "user"]
(ns-name *ns*) => user
我们看到*ns*
被设置为用户
名称空间,happy
无法解析为Vardemo.core/happy
,除非我们手动或在代码中使用语法引号
对其进行完全限定
你可以找到一份工作。一定要特别学习Clojure备忘单
对于宏,这本书也很好。宏函数不会返回代码,但会立即打印。这是一种非常糟糕的风格,因为它会带来意想不到的后果
如果要使用此功能:
(defn hello [] (Simple))
创建函数时,它会打印“Hello”。插入函数的代码是println
的结果,即nil
,因此您创建了以下代码:
(defn hello [] nil)
然后,如果调用hello
3次,则所有调用都不会进行任何打印,因为宏只生成nil
。如果将宏更改为返回结构:
;; The quote that makes all the difference
(defmacro Simple [] '(println "Hello"))
在创建hello
的过程中,if将不会打印任何内容,但扩展将是(println“hello”)
,相同的功能hello
将变成:
(defn hello [] (println "Hello"))
(defn hello [] (println "Hello"))