在 Clojure 中执行静态初始化程序而不在编译时使用它 运行 的惯用方法是什么?

What is the idiomatic way to do a static initializer in Clojure without having it run on compilation?

我想在 Clojure 中做一个类似于您在 Java 中可以做的静态初始化程序。

public class Test {

    static{
        System.out.println("Static");
    }

    public static void main(String[] args) {
        System.out.println("Static main");
    }
}

现在我知道你可以这样做:

(ns myns)

(defn my-func [] (println "my-func called"))

(my-func)

但这将是 运行 在编译时,我想避免。

我能做的是从 Java class 中的静态初始值设定项调用它,然后关闭 AOT 编译,但这似乎不是惯用的。

我的问题是:在 Clojure 中执行静态初始值设定项而不在编译时 运行 的惯用方法是什么?

我通常看到命名空间资源在运行时初始化而不是编译时的方式是使用延迟:

(defn init-resource [] ...)

(def my-resource (delay (init-resource)))

(defn do-something []
  (let [r @my-resource] ...))

这不是您要查找的内容,因为 my-resource 在调用 do-something 之前不会初始化,这可能是在加载命名空间之后。

如果硬性要求在加载命名空间时完成初始化,您可以将初始化代码包装在一些代码中,检查 clojure.core/*compile-files* 标志以查看是否正在编译代码。但是,我不会完全称之为惯用语:

(defn init-resource [] ...)

(defmacro do-runtime [& body]
  `(when-not *compile-files* ~@body))

(def my-resource (do-runtime (init-resource)))

(defn do-something []
  (let [r my-resource] ...))