我有一个包含以下ns的项目:
在processor.pubsub我有以下内容:
(ns processor.pubsub
(:gen-class))
(defrecord PubsubBus [client])
; + other stuff related to this implementation
在processor.bus中,我有:
(ns tiptop.processor.bus
(:gen-class)
(:import [processor.pubsub PubsubBus]))
(defprotocol SendToBus
(send-line! [self json]))
(extend-type PubsubBus
SendToBus
....)
Lein没有按正确的顺序编译命名空间的问题。我收到以下错误:
$ lein compile
Compiling user
Compiling processor.auth
Compiling processor.bus
java.lang.ClassNotFoundException: processor.pubsub.PubsubBus, compiling:(bus.clj:1:1)
Exception in thread "main" java.lang.ClassNotFoundException: processor.pubsub.PubsubBus, compiling:(bus.clj:1:1)
请注意,它尝试按字母顺序编译我的ns(auth - > bus - > pubsub),而不是依赖顺序。
当然我之前可以预编译pubsub.clj,例如:
$ lein compile processor.pubsub
$ lein compile processor.bus
$ lein compile
但它对我来说似乎并不合适。如果我有更多这样的依赖名称空间怎么办?
我如何告诉Lein它应该以哪种顺序编译我的命名空间?或者我可能错过了在project.clj
中配置的内容?如果重要的话我有:aot :all
答案 0 :(得分:6)
Leiningen没有做任何事情来确定命名空间依赖关系 - 它只是编译你告诉它的命名空间。 Clojure编译器通过require
(以及过时的use
)内置函数处理命名空间依赖关系。
在这种情况下,您需要:require
定义生成的类的命名空间,然后才能导入它。否则,您依赖于类路径中存在的导入类作为其他操作的副作用(加载在REPL中定义它的命名空间,先前的lein compile
命令等)。在命名空间定义中添加显式:require
可确保在导入之前定义类:
(ns processor.bus
(:gen-class)
(:require [processor.pubsub])
(:import [processor.pubsub PubsubBus]))
其他几点说明:
:gen-class
正在做你认为它在这些命名空间声明中所做的事情。它不会导致为这些名称空间中定义的协议和记录编写类文件;这就是Leiningen :aot
中project.clj
密钥的含义。此处使用的:gen-class
标志将生成名为processor.bus
和processor.pubsub
的类。extend-type
指定的具体记录类型的协议实现详细信息是不常见的。 extend-type
的典型用例是扩展协议以使用无法控制的类型,例如内置于Clojure或在第三方库中定义的类型。当协议和记录在同一个项目中定义时,更常见的是将协议实现作为defrecord
正文的一部分内联定义。