我有一个以下ns项目:


Processor.bus Processor.core Processor.pubsub

在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)


注意,它会尝试按字母顺序(auth-> bus-> pubsub)编译我的ns,而不是依赖关系顺序。

当然,我可以预先编译pubsub.clj,例如:

$ lein compile processor.pubsub
$ lein compile processor.bus
$ lein compile


但这对我来说似乎不太正确。如果我将拥有更多这样的依赖命名空间怎么办?

我怎样才能告诉Lein应该以什么顺序编译我的命名空间?或者,也许我缺少要在project.clj中配置的内容?如果有的话我有:aot :all

最佳答案

Leiningen不会做任何事情来确定名称空间的依赖关系,它只是编译您告诉它的名称空间。 Clojure编译器通过require(和过时的use)内置函数处理名称空间相关性。

在这种情况下,您需要先:require定义所生成类的名称空间,然后才能将其导入。否则,您将依赖于导入在类路径上的类,这是其他操作的副作用(在REPL中加载定义它的名称空间,之前的lein compile命令等)。在名称空间定义中添加一个明确的:require可以确保在导入该类之前对其进行定义:

(ns processor.bus
  (:gen-class)
  (:require [processor.pubsub])
  (:import [processor.pubsub PubsubBus]))


其他一些注意事项:


我怀疑是否正在执行您在这些名称空间声明中所做的事情。它不会导致为这些命名空间中定义的协议和记录编写类文件;这就是Leiningen :gen-class中的:aot键。此处使用的project.clj标志将导致生成名为:gen-classprocessor.bus的类。
在定义协议的同一名称空间中,通过processor.pubsub指定的具体记录类型的协议实现详细信息,通常是不常见的。 extend-type的典型用例是扩展协议以使其能够使用超出您控制范围的类型,例如Clojure内置的或在第三方库中定义的类型。当协议和记录在同一项目中定义时,通常将协议实现内联定义为extend-type主体的一部分。

09-16 06:38
查看更多