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

52

我在寻找Clojure命名空间的最佳实践和常规用法方面遇到了困难。我意识到命名空间并不同于Java包,因此我正在尝试梳理Clojure中的惯例,但这似乎异常困难。

我认为我已经有了将函数分割成clj文件的良好想法,甚至大致知道如何将这些文件组织到目录中。但是在此之上,在我的开发环境中,我遇到了一些问题:

  1. 我应该像Java包一样使用相同的唯一性约定来命名Clojure命名空间吗?[例如:倒置公司域.项目名称.子系统名称]
  2. 我应该将文件保存在与命名空间匹配的目录结构中吗?[类似Java]
  3. 如果我有多个命名空间,是否需要将所有代码编译成一个JAR文件并将其添加到类路径中以使其可访问?
  4. 每个命名空间是否应编译为一个JAR文件?还是应该创建一个包含多个命名空间的单个JAR文件?

谢谢...


6
我衷心为这篇博客点赞,如果我在编写这个问题时看到了它,会对我很有帮助:http://blog.8thlight.com/articles/2010/12/6/clojure-libs-and-namespaces-require-use-import-and-ns - Alex Miller
2个回答

43
  1. 如果您认为这有帮助,那么使用顶层命名空间和特定功能的命名空间(例如compojure.*)是许多Clojure项目所采用的做法。但Clojure本身使用clojure.*作为命名空间(contrib库则使用clojure.contrib.*),但我想这是一种特殊情况。

  2. 是的!您必须这样做,否则Clojure将无法找到您的命名空间。还请注意,在命名空间名称中不要使用下划线,在文件名中不要使用连字符,并且无论何时在命名空间名称中使用连字符,您都必须在文件名中使用下划线(例如ns my.cool-project 定义在名为cool_project.clj 的文件中,在名为my 的目录中)。

  3. 您需要确保所有东西都位于classpath上,但是它们是在一个jar中、多个jar中、在文件系统上的目录和jar的混合物中都没有关系...只要它遵守正确的命名约定(您的第2点),就应该可以正常运行。

    但是,如果没有特殊原因,请不要提前编译代码- 这可能会使您的代码在各个Clojure版本之间无法移植,并且除了稍微改善加载时间之外,不提供任何好处。

    有时仍需要使用AOT编译,尤其是在某些Java交互操作场景中- 相关函数/宏的文档总是提到此事。在clojure.contrib中有一些需要AOT的示例;我从未需要过,因此无法提供太多详细信息。

  4. 我建议您将代码的功能单元打包成jar文件。例如,Compojure和Ring被打包为包含许多命名空间的单个jar文件,这些命名空间组合在一起形成整个包。此外,clojure.contrib 被打包为一个具有多个不相关库的单个jar文件;但那可能又是一种特殊情况。

另一方面,一个只包含您项目中所有代码及其依赖项的单个 Jar 文件在部署时可能会偶尔有用。如果您认为这样的工具可能对您有用,请查看 Leiningen 构建工具 及其 'uberjar' 功能。


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

关于3和4,打包和AOT编译与命名空间约定的问题完全无关。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接