1

我在一个 ns 中定义了以下内容 -

有一个服务原子,还有另一个要添加到该原子的函数 -

(ns ex.first)

(def services (atom []))

(defn add-service
  [fns]
  (swap! services conj fns))

在另一个ns的代码中,我这样做-

(ns ex.second ..)

(add-service [fn1 fn2 fn3])

1)我假设当我运行编译代码的repl时,它应该将向量添加到原子。但是,当我评估@services它时,它会返回[]

2)如果我(add-service [fn1 fn2 fn3])在repl中评估,上述方法有效。

3)我也尝试使用将add-servicefn 转换为宏。但是我仍然发现它@services是空的。

因此,如果有人可以帮助解决这些问题,我们将不胜感激-

1)为什么 add-service 调用在代码编译时不向原子添加向量 -

  • add-service被定义为一个fn
  • add-service被定义为一个macro

2)我如何使它工作:)

4

1 回答 1

4

这取决于您是否已:aot:allproject.clj 中设置。

如果:aot:all,则函数调用将在 repl 启动后立即执行,否则您将需要加载ex.second命名空间(例如: using use)。加载将导致ns被编译并在jvm中加载相应的类并执行函数调用。

此外,函数调用不会发生在编译时,它发生在 jvm 加载编译的类(代表命名空间)时。

更新(基于评论):

如果你把它变成一个宏,那么你也需要考虑 aot 的东西。

如果 aot 被设置为编译命名空间,那么 lein 会创建一个 jvm,在其中加载你的代码,调用 clojure 编译器,它会读取代码,执行宏并编译代码,此时这个 jvm(用于编译你的代码)将有services原子填充的宏执行,但这个jvm仅用于编译。然后 lein 将为运行命令创建另一个 jvm 并在该 jvm 中加载已编译的类,但是这个 jvm 不会services填充,因为类没有任何代码来填充它。

如果未设置 aot,则宏将起作用,因为读取、宏扩展、编译过程将在 lein run jvm 中发生,但仅当您导致加载 ns 时才会发生。

就“不加载 ns”而言,您可以做的是将project.cljex.second中的:aot

于 2013-04-04T08:57:05.440 回答