Lein使用协议编译项目

Igo*_*nov 2 clojure leiningen

我有一个带有以下ns的项目:

  • processor.bus < - 总线操作的通用协议
  • processor.core < - 要运行的主类
  • processor.pubsub < - 具体的总线方法

在processor.pubsub我有以下内容:

(ns processor.pubsub
  (:gen-class))

(defrecord PubsubBus [client])

; + other stuff related to this implementation
Run Code Online (Sandbox Code Playgroud)

在processor.bus我有:

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

(defprotocol SendToBus
  (send-line! [self json]))

(extend-type PubsubBus
  SendToBus
  ....) 
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

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

当然我之前可以预编译pubsub.clj,比如:

$ lein compile processor.pubsub
$ lein compile processor.bus
$ lein compile
Run Code Online (Sandbox Code Playgroud)

但它似乎不适合我.如果我有更多这样的依赖命名空间怎么办?

我如何告诉Lein它应该以哪种顺序编译我的命名空间?或者也许我错过了配置的东西project.clj:aot :all如果重要我有

Ale*_*lex 6

Leiningen没有做任何事情来确定命名空间依赖关系 - 它只是编译你告诉它的命名空间.Clojure编译器通过require(和过时的use)内置函数处理命名空间依赖关系.

在这种情况下,您需要先:require定义生成的类的命名空间,然后才能导入它.否则,您依赖于类路径中存在的导入类作为某些其他操作的副作用(加载在REPL中定义它的命名空间,以前的lein compile命令等).:require在命名空间定义中添加显式可确保在导入之前定义类:

(ns processor.bus
  (:gen-class)
  (:require [processor.pubsub])
  (:import [processor.pubsub PubsubBus]))
Run Code Online (Sandbox Code Playgroud)

其他几点说明:

  • 我怀疑:gen-class你正在做这些名称空间声明中正在做的事情.它不会导致为这些名称空间中定义的协议和记录编写类文件; 这:aot就是Leiningen 的关键所在project.clj.:gen-class这里使用的标志将导致命名processor.busprocessor.pubsub生成的类.
  • 通过extend-type在定义协议的同一命名空间中查看指定的具体记录类型的协议实现细节是不常见的.典型的用例extend-type是扩展协议以使用无法控制的类型,例如内置于Clojure或在第三方库中定义的类型.当协议和记录在同一个项目中定义时,更常见的是将内联定义的协议实现作为defrecord正文的一部分.