2010-06-24 32 views
14

我正在用多個子結構在Clojure中開發一個複雜的數據結構。從Clojure中抽象出數據結構的實現細節

我知道我會希望隨着時間的推移來擴展這個結構,並且有時可能想改變內部結構而不會破壞數據結構的不同用戶(例如,我可能想要將矢量變成散列表,添加某些類型的索引結構的性能方面的原因,或結合了Java類型)

我現在的想法是:

  • 定義一個協議與各種存取方法的整體結構
  • 創建的一個小型圖書館導航數據結構的功能e 。G。 (查詢子-ABC參數1參數2)
  • 實現使用defrecord或DEFTYPE數據結構,定義爲使用小型圖書館

我認爲這將工作在協議方式,但我很擔心它開始看起來像很多「膠水」代碼。另外它也可能反映了我對面向對象方法的更加熟悉。

在Clojure中做這件事的推薦方式是什麼?

回答

11

我認爲deftype可能是要走的路,但我會採取accessor方法。相反,看看clojure.lang.ILookupclojure.lang.Associative;這些接口可以讓你使用get/get-inassoc/assoc-in,這是一個更加通用的解決方案(不僅可以改變底層實現,還可以使用基於Clojure標準集合庫構建的函數來操縱你的結構)。

幾件事情需要注意:

  1. 你或許應該defrecord開始,用getassoc &有限公司與ILookupAssociativeIPersistentMapjava.util.Map標準defrecord實現。你可能會用它很長的路。

    如果/當這些不夠時,請查看emit-defrecord(Clojure源中的core_deftype.clj中定義的私有函數)的來源。這非常複雜,但它會讓你知道你可能需要實現什麼。

  2. deftypedefrecord目前都沒有爲您定義任何工廠函數,但您應該自己做。在這些功能(和/或相應的測試)中進行完整性檢查。

  3. 的多個概念的複雜操作的過程中對協議功能的完美契合建立在get &有限公司

哦基礎,看看在Clojure的來源gvec.clj的示例使用deftype編寫的一些嚴重的數據結構代碼可能看起來像什麼。這裏的複雜性與您在問題中描述的不同,但它仍然是Clojure目前可用於公共消費的自定義數據結構編程的少數幾個例子之一(當然,它也是優秀的代碼)。

當然,這正是我的直覺告訴我的。我不確定現階段已確立的習語存在多少問題,但deftype實際上並未發佈,並且全部。 :-)

+0

謝謝Michal!洞察力一如既往:-)肯定會研究ILookup和關聯選項 – mikera 2010-06-25 13:54:25

+0

這是一個非常有用的答案!但是將近三年後,基於現在可用的1.5版本的功能更新它(或創建一個新的答案)會很好。我注意到的一件事是'defrecord'現在發出工廠函數,不知道其他更改可能會影響此答案。 – 2013-05-01 17:11:58

+0

我認爲這個答案也可以使用更新 - 即使是O'Reily Clojure的書現在也說clojure的defrecord會創建工廠函數。 – djhaskin987 2013-09-01 02:47:55