在Clojure中使用命名空间的常见约定是什么?

Ale*_*ler 50 namespaces conventions clojure project-organization

我在Clojure中找到使用命名空间的好建议和常用做法时遇到了麻烦.我意识到命名空间与Java包不同,所以我试图梳理Clojure中的约定,这似乎很难确定.

我想我非常清楚如何将函数分成clj文件,甚至大致如何将这些文件组织到目录中.但除此之外,我无法为我的开发环境找到机制.一些相互关联的问题:

  1. 对于Clojure命名空间,我是否使用与通常用于Java包的相同的唯一性约定?[即backwards-company-domain.project.subsystem]
  2. 我应该将文件保存在与我的命名空间匹配的目录结构中吗?[ala Java]
  3. 如果我有多个名称空间,是否需要将所有代码编译到jar中并将其添加到我的类路径中以使其可访问?
  4. 每个命名空间应该编译成一个jar吗?或者我应该创建一个包含来自许多名称空间的clj代码的jar?

谢谢...

Mic*_*zyk 41

  1. 我想如果你觉得它有帮助就行了,但很多Clojure项目都不这样做 - 参见 Compojure(使用顶级组件ns和各种组件.*ns用于特定功能),Ring,Leiningen ...... Clojure本身使用clojure.*(和contrib库的clojure.contrib.*),但这是一个特例,我想.

  2. 是! 你绝对必须这样做,否则Clojure将无法找到你的命名空间.另请注意,您不使用命名空间名称中的下划线或文件名中的连字符以及在命名空间名称中使用连字符的任何位置,您必须在文件名中使用下划线(以便ns my.cool-project在一个名为的文件cool_project.clj中定义目录叫my).

  3. 你需要确保你的所有东西都在类路径上,但是如果它在jar,多个jar,混合的jar和文件系统上的目录中都没关系...只要它遵循正确的命名约定(你的观点2)你应该没事.

    但是,如果没有特别的理由,请不要提前编译 - 这可能会阻止您的代码在各种版本的Clojure中移植,除了略微改进的加载时间之外没有任何好处.

    您有时仍需要使用AOT编译,特别是在某些Java互操作方案中 - 相关函数/宏的文档总是提到这一点.在clojure.contrib中有一些需要AOT的例子; 我从来不需要它,所以我不能提供太多的细节.

  4. 我会说你应该使用jar作为代码的功能单元.例如,Compojure和Ring被打包为包含许多名称空间的单个jar,这些名称空间共同构成整个包.此外,clojure.contrib特别打包为具有多个不相关库的单个jar; 但这又可能是一个特例.

    另一方面,包含所有项目代码及其依赖项的单个jar可能偶尔对部署有用.查看Leiningen构建工具及其"uberjar"工具,如果您认为这类工具可能对您有用.


cem*_*ick 10

  1. 严格来说,没有必要,尽管许多Java项目也放弃了这种约定,特别是对于内部项目或私有API.但是,请避免使用单段命名空间,这会导致在默认包中生成类文件.
  2. 是.

关于3和4,封装和AOT编译完全与命名空间约定问题正交.