在 Clojure 中使用命名空间的常见约定有哪些?
我无法找到在 Clojure 中使用命名空间的好的建议和常见做法。我意识到命名空间与 Java 包不同,因此我试图梳理 Clojure 中的约定,这些约定似乎很难确定。
我认为我非常清楚如何将函数拆分为 clj 文件,甚至大致知道如何将这些文件组织到目录中。但除此之外,我很难找到适合我的开发环境的机制。一些相互关联的问题:
- 我是否对 Clojure 命名空间使用与通常用于 Java 包相同的唯一性约定? [即backwards-company-domain.project.subsystem]
- 我应该将文件保存在与我的命名空间匹配的目录结构中吗? [ala Java]
- 如果我有多个命名空间,我是否需要将所有代码编译到一个 jar 中并将其添加到我的类路径中以使其可访问?
- 每个命名空间都应该编译成一个 jar 吗?或者我应该创建一个包含来自多个命名空间的 clj 代码的单个 jar?
谢谢...
I'm having trouble finding good advice and common practices for the use of namespaces in Clojure. I realize that namespaces are not the same as Java packages so I'm trying to tease out the conventions in Clojure, which seem surprisingly hard to determine.
I think I have a pretty good idea how to split functions into clj files and even roughly how I'd want to organize those files into directories. But beyond that I'm having trouble finding the mechanics for my dev environment. Some inter-related questions:
- Do I use the same uniqueness conventions for Clojure namespaces as I would normally use for Java packages? [ie backwards-company-domain.project.subsystem]
- Should I save my files in a directory structure that matches my namespaces? [ala Java]
- If I have multiple namespaces, do I need to compile all of my code into a jar and add it to my classpath to make it accessible?
- Should each namespace compile to one jar? Or should I create a single jar that contains clj code from many namespaces?
Thanks...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我想如果您认为它有帮助就没关系,但许多 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 和目录的混合中都没关系......只要它遵循正确的规则命名约定(你的第二点)应该没问题。
但是,如果没有特殊原因,请不要提前编译内容 - 这可能会阻止您的代码在不同版本的 Clojure 之间移植,除了提供以下好处之外,没有任何好处:加载时间略有改善。
有时您仍然需要使用 AOT 编译,特别是在某些 Java 互操作场景中 - 相关函数/宏的文档总是提到这一点。 clojure.contrib中有需要AOT的东西的例子;我从来没有需要过它,所以我无法提供太多细节。
我想说你应该使用 jars 作为代码的功能单元。例如,Compojure 和 Ring 被打包为单个 jar,其中包含许多名称空间,这些名称空间共同组成了整个包。此外,clojure.contrib 值得注意的是,它被打包为具有多个不相关库的单个 jar;但这可能又是一个特殊情况。
另一方面,包含所有项目代码及其依赖项的单个 jar 有时可能对部署有用。如果您认为此类东西可能有用,请查看 Leiningen 构建工具 及其“uberjar”工具你。
I guess it's ok if you think it helps, but many Clojure projects don't do so -- cf. Compojure (using a top-level compojure ns and various compojure.* ns's for specific functionality), Ring, Leiningen... Clojure itself uses clojure.* (and clojure.contrib.* for contrib libraries), but that's a special case, I suppose.
Yes! You absolutely must do so, or else Clojure won't be able to find your namespaces. Also note that you musn't use the underscore in namespace names or the hyphen in filenames and wherever you use a hyphen in a namespace name, you must use an underscore in the filename (so that the ns
my.cool-project
is defined in a file calledcool_project.clj
in a directory calledmy
).You need to make sure all your stuff is on the classpath, but it doesn't matter if it's in a jar, multiple jars, a mixture of jars and directories on the filesystem... As long as it obeys the correct naming conventions (your point no. 2) you should be fine.
However, do not compile things ahead-of-time if there's no particular reason to do so -- this may prevent your code from being portable across various versions of Clojure without providing any benefits besides a slightly improved loading time.
You'll still need to use AOT compilation sometimes, notably in some Java interop scenarios -- the documentation of the relevant functions / macros always mentions that. There are examples of things requiring AOT in clojure.contrib; I've never needed it, so I can't provide much in the way of details.
I'd say you should use jars for functional units of code. E.g. Compojure and Ring get packaged as single jars containing many namespaces which together compose the whole package. Also, clojure.contrib is notably packaged as a single jar with multiple unrelated libraries; but that again may be a special case.
On the other hand, a single jar containing all of your project's code together with its dependencies might occasionally be useful for deployment. Check out the Leiningen build tool and its 'uberjar' facility if you think that sort of thing may be useful to you.
关于3& 4、打包和AOT编译与命名空间约定问题完全正交。
Regarding 3 & 4, packaging and AOT compilation are entirely orthogonal to the question of namespace conventions.