sip*_*uel 4 macros clojure uberjar leiningen
下面是一个简单的Clojure应用程序示例lein new mw
:
(ns mw.core
(:gen-class))
(def fs (atom {}))
(defmacro op []
(swap! fs assoc :macro-f "somevalue"))
(op)
(defn -main [& args]
(println @fs))
Run Code Online (Sandbox Code Playgroud)
在project.clj
我有
:profiles {:uberjar {:aot [mw.core]}}
:main mw.core
Run Code Online (Sandbox Code Playgroud)
在REPL中运行时,评估@fs
返回值{:macro-f somevalue}
.但是,运行一个uberjar收益率{}
.如果我改为op
定义defn
而不是defmacro
,那么fs
当从uberjar运行时再次有适当的内容.这是为什么?
我隐约意识到这与AOT编译有关,并且宏编译在编译阶段之前发生,但显然我对这些事情的理解是缺乏的.
我在尝试部署使用非常好的mixfix库的应用程序时遇到了这个问题,其中mixfix运算符是使用全局原子定义的.我花了很长时间才将问题与上面提到的例子隔离开来.
任何帮助将不胜感激.
谢谢!
这里真正的问题是你的宏不正确.你忘了添加反引号字符:
(defmacro op []
`(swap! fs assoc :macro-f "somevalue"))
; ^ syntax-quote ("backquote")
Run Code Online (Sandbox Code Playgroud)
这个操作叫做syntax-quote,这里非常重要,因为clojure中的宏在编译时会修改你的代码.
因此,结果你得到了一个不纯的宏,fs
只要编译代码就修改原子.
由于您的宏不生成任何代码,因此(op)
在您的示例中调用什么都不做(只有它的编译才能执行).它似乎在REPL中工作,因为编译和执行由同一个clojure实例处理(详见Timur的答案).
归档时间: |
|
查看次数: |
167 次 |
最近记录: |