在使用 :gen-class
进行提前编译时,是否可以将 Clojure 命名空间拆分为多个源文件? (:main true)
和 (defn- ...)
如何发挥作用?
最佳答案
概述
当然可以,事实上 clojure.core
命名空间本身就是这样划分的,并提供了一个很好的模型,您可以通过查看 src/clj/clojure
来遵循该模型:
core.clj
core_deftype.clj
core_print.clj
core_proxy.clj
..etc..
所有这些文件都参与构建单个 clojure.core
命名空间。
主文件
其中一个是主文件,其命名与命名空间名称相匹配,以便当有人在 :use
或 :require
中提及它时可以找到它。在本例中,主文件是 clojure/core.clj
,它以 ns
形式开头。这是您应该放置所有命名空间配置的位置,无论您的其他哪些文件可能需要它们。这通常也包括 :gen-class
,所以类似:
(ns my.lib.of.excellence
(:use [clojure.java.io :as io :only [reader]])
(:gen-class :main true))
然后在主文件中的适当位置(最常见的是在末尾)使用 load
引入辅助文件。在 clojure.core 中,它看起来像这样:
(load "core_proxy")
(load "core_print")
(load "genclass")
(load "core_deftype")
(load "core/protocols")
(load "gvec")
请注意,您不需要当前目录作为前缀,也不需要 .clj
后缀。
帮助文件
每个帮助程序文件都应首先声明它们正在帮助的命名空间,但应使用 in-ns
函数来执行此操作。因此,对于上面的示例命名空间,帮助程序文件都以以下内容开头:
(in-ns 'my.lib.of.excellence)
仅此而已。
一代
由于所有这些文件都构建单个命名空间,因此您定义的每个函数都可以位于任何主文件或辅助文件中。这当然意味着您可以在任何您想要的文件中定义您的gen-class
函数:
(defn -main [& args]
...)
请注意,Clojure 的正常定义顺序规则仍然适用于所有函数,因此您需要确保在尝试使用之前加载定义函数的任何文件 em>那个函数。
私有(private)变量
您还询问了定义命名空间私有(private)函数的 (defn- foo ...)
形式。像这样定义的函数以及其他 :private
变量在定义它们的命名空间内是可见的,因此主文件和所有辅助文件都可以访问在任何加载的文件中定义的私有(private)变量到目前为止。
关于namespaces - 将 Clojure 命名空间拆分为多个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4690758/