【问题标题】:What are common conventions for using namespaces in Clojure?在 Clojure 中使用命名空间的常见约定是什么?
【发布时间】:2011-01-14 10:57:57
【问题描述】:
我很难找到在 Clojure 中使用命名空间的好建议和常见做法。我意识到名称空间与 Java 包不同,所以我试图梳理出 Clojure 中的约定,这似乎很难确定。
我想我对如何将函数拆分为 clj 文件,甚至大致了解我希望如何将这些文件组织到目录中都有一个很好的想法。但除此之外,我很难找到适合我的开发环境的机制。一些相互关联的问题:
- 我是否对 Clojure 命名空间使用与通常用于 Java 包的相同的唯一性约定? [即backwards-company-domain.project.subsystem]
- 我应该将我的文件保存在与我的命名空间匹配的目录结构中吗? [ala Java]
- 如果我有多个命名空间,我是否需要将我的所有代码编译到一个 jar 中并将其添加到我的类路径中以使其可访问?
- 每个命名空间都应该编译成一个jar吗?或者我应该创建一个包含来自许多命名空间的 clj 代码的单个 jar?
谢谢...
【问题讨论】:
标签:
namespaces
clojure
conventions
project-organization
【解决方案1】:
我想如果您认为它有帮助也没关系,但是许多 Clojure 项目并没有这样做——参见。 Compojure(使用顶级 compojure ns 和各种 compojure.* ns 用于特定功能)、Ring、Leiningen... Clojure 本身使用 clojure.*(和 clojure.contrib.* 用于 contrib 库),但这是一种特殊情况,我想。
是的!您绝对必须这样做,否则 Clojure 将无法找到您的命名空间。另请注意,您不得在命名空间名称中使用下划线或在文件名中使用连字符,并且无论在命名空间名称中使用连字符的任何位置,都必须在文件名中使用下划线(以便 ns my.cool-project 在文件中定义在名为my 的目录中调用cool_project.clj)。
-
你需要确保你所有的东西都在类路径中,但不管它是在一个 jar、多个 jar、文件系统上的 jar 和目录的混合......只要它遵守正确的命名约定(你的第 2 点)你应该没问题。
但是,如果没有特别的理由,不要提前编译东西——这可能会阻止你的代码在 Clojure 的不同版本之间移植,除了提供任何好处之外加载时间略有改善。
您有时仍需要使用 AOT 编译,尤其是在某些 Java 互操作场景中——相关函数/宏的文档总是提到这一点。 clojure.contrib 中有一些需要 AOT 的例子;我从来不需要它,所以我不能提供太多细节。
-
我会说您应该将 jar 用于代码的功能单元。例如。 Compojure 和 Ring 被打包为包含许多名称空间的单个 jar,这些名称空间共同构成了整个包。此外,clojure.contrib 被打包为带有多个不相关库的单个 jar;但这又可能是一个特例。
另一方面,包含所有项目代码及其依赖项的单个 jar 有时可能对部署很有用。如果您认为这类东西可能对您有用,请查看 the Leiningen build tool 及其“uberjar”工具。
【解决方案2】:
- 严格来说,没有必要,尽管许多 Java 项目也放弃了该约定,尤其是对于内部项目或私有 API。但是请避免使用单段命名空间,这会导致在默认包中生成类文件。
- 是的。
关于 3 和 4,打包和 AOT 编译与命名空间约定问题完全正交。