[英]How to aot-compile gen-class classes with cyclic type hints?
在Clojure中,我将gen-class
与Java库一起使用。 程序员通常提供两个类,分别实现一个接口和扩展一个类。 这两个类应该相互引用,并且鉴于库的设计方式,很难避免这种循环依赖性。
周期不是问题-编译器不必了解它们-除非我试图通过明智地添加类型提示(以大幅度的加速)来优化代码。 通过重组代码,我能够避免编译器抱怨循环依赖,并将问题简化为单个类型提示:
在一个源文件Foo.clj中,我具有此函数/方法,该方法/方法是类实现的接口所必需的:
(defn -step
[^Foo this ^Bar bar]
...)
另一个源文件Bar.clj创建了Foo实例的集合,因此我必须在此引用Foo类。 在我的Leiningen project.clj中,我有这样一行:
:aot [Foo Bar]
我没有周期性的依赖错误。 相反,我得到ClassNotFoundException
:如果我将Foo
放在:aot
,则编译器会抱怨它在编译Foo
时不了解Bar
,因为^Bar
类型提示在-step
。 如果我将Bar
放在:aot
,则编译器在编译Bar
时找不到Foo
,这是因为Bar.clj中对(Foo.)
的调用。
我当前的解决方案是这样的:
^Bar
类型暗示的定义-step
在Foo.clj。 -step
在Foo.clj。 Foo
(即再次运行“ lein compile”)。 之所以可行,是因为第二次编译Foo
时, Bar
存在,因此编译器不会抱怨。
有没有一种方法可以编译两个类而又不删除并重新添加类型提示? (或者我应该考虑这种情况的另一种方式?)
我的倾向是在foo名称空间中为Foo添加一个工厂函数。
(defn new-foo [] (Foo.)) ; parameterize to your satisfaction
然后,您可以在以下答案中使用前向声明技术来从Bar中访问new-foo-从Clojure中的另一个命名空间中前向声明var?
当然,这仍然很棘手-如果还有其他方法可以打破依赖关系循环,则可以采取这种方法。 如果可以的话,如何在同一个命名空间中定义Foo和Bar? 它们看起来确实紧密耦合,尽管很难用抽象的问题描述来说明。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.