繁体   English   中英

如何使用循环类型提示对gen-class类进行aot编译?

[英]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.)的调用。

我当前的解决方案是这样的:

  1. 删除^Bar类型暗示的定义-step在Foo.clj。
  2. 编译两个类。
  3. 添加类型提示回-step在Foo.clj。
  4. 编译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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM