簡體   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