In Clojure, I'm using gen-class
with a Java library. The programmer normally provides two classes that implement an interface and extend a class, respectively. The two classes are supposed to refer to each other, and it's hard to avoid this cyclic dependency given the way the library is designed.
The cycles wouldn't be a problem--the compiler doesn't have to know about them--except that I'm trying to optimize the code by judiciously adding type hints (with huge speedups). I've been able to avoid compiler complaints about cyclic dependencies by reorganizing the code, and I've reduced the problem to a single type hint:
In one source file, Foo.clj, I have this function/method, which is required by the interface the class implements:
(defn -step
[^Foo this ^Bar bar]
...)
Another source file, Bar.clj, creates a collection of instances of Foo, so I have to refer to the Foo class there. In my Leiningen project.clj, I have a line like this:
:aot [Foo Bar]
I don't get a cyclic dependency error. Instead I get a ClassNotFoundException
: If I put Foo
first after :aot
, the compiler complains that it doesn't know about Bar
when it compiles Foo
, because of the ^Bar
type hint in -step
. If I put Bar
first after :aot
, the compiler can't find Foo
when it compiles Bar
, because of the calls to (Foo.)
in Bar.clj.
My current solution is this:
- Delete the
^Bar
type hint in the definition of-step
in Foo.clj. - Compile both classes.
- Add the type hint back in
-step
in Foo.clj. - Compile
Foo
(i.e. run 'lein compile` again).
This works because when Foo
is compiled the second time, Bar
exists, so the compiler doesn't complain.
Is there a way to compile both classes without deleting and adding back the type hint? (Or a different way that I should think about this situation?)