【发布时间】:2016-01-17 22:05:33
【问题描述】:
下面是一个使用lein new mw 创建的简单 Clojure 应用示例:
(ns mw.core
(:gen-class))
(def fs (atom {}))
(defmacro op []
(swap! fs assoc :macro-f "somevalue"))
(op)
(defn -main [& args]
(println @fs))
在project.clj 我有
:profiles {:uberjar {:aot [mw.core]}}
:main mw.core
在 REPL 中运行时,评估 @fs 返回 {:macro-f somevalue}。但是,运行 uberjar 会产生 {}。如果我将op 定义更改为defn 而不是defmacro,那么fs 在从uberjar 运行时再次具有正确的内容。这是为什么呢?
我隐约意识到这与AOT编译以及宏扩展发生在编译阶段之前的事实有关,但显然我对这些事情的理解不足。
我在尝试部署一个使用非常好的 mixfix 库的应用程序时遇到了这个问题,其中 mixfix 运算符是使用全局原子定义的。我花了很长时间才将问题与上述示例隔离开来。
任何帮助将不胜感激。
谢谢!
【问题讨论】:
-
宏用于在编译期间修改“clojure-source-code”。因为
op没有要修改的输入,所以我问你——在你看来,op应该做什么?宏(因为它们在编译时“运行”)在 java 字节码/类文件中不存在。编辑:捕获或产生“来自/进入外部范围的东西”的宏也称为非卫生宏,处理起来特别繁琐。 -
不纯的宏是个很邪恶的东西。不过,可能你只是忘了用反引号 ` 字符引用它。
-
@leonid-beschastny - 我试图通过
op宏来反映 mixfix 使用的行为。 -
@birdspider - 感谢您解释什么是非卫生宏。
标签: clojure macros leiningen uberjar