2010-06-24 70 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