摘要远离Clojure中的数据结构实现细节

mik*_*era 14 encapsulation abstraction clojure data-structures

我正在Clojure中开发一个具有多个子结构的复杂数据结构.

我知道我会想要随着时间推移扩展这个结构,有时可能想要改变内部结构而不会破坏数据结构的不同用户(例如我可能想要将一个向量更改为一个hashmap,添加某种索引出于性能原因的结构,或者包含Java类型)

我目前的想法是:

  • 使用各种访问器方法为整体结构定义协议
  • 创建一个导航数据结构的迷你函数库,例如(query-substructure-abc param1 param2)
  • 使用defrecord或deftype实现数据结构,并使用定义的协议方法来使用迷你库

我认为这会有效,但我担心它开始看起来像很多"胶水"代码.它也可能反映了我对面向对象方法的更多熟悉.

在Clojure中推荐的方法是什么?

Mic*_*zyk 11

我认为这deftype可能是要走的路,但是我会通过访问器方法.相反,看看clojure.lang.ILookupclojure.lang.Associative; 这些接口,如果你为你的类型实现它们,将允许你使用get/ get-inassoc/ assoc-in,提供一个更通用的解决方案(不仅你能够改变底层实现,但也许也可以使用建立在顶层的功能Clojure的标准集合库来操纵你的结构).

有几点需要注意:

  1. 你或许应该开始defrecord使用get,assoc及公司与标准defrecord的实现ILookup,Associative,IPersistentMapjava.util.Map.你可能会用它走很长的路.

    如果/当这些不再足够时,请查看emit-defrecord(core_deftype.cljClojure源中定义的私有函数)的源代码.它非常复杂,但它可以让您了解可能需要实现的内容.

  2. 既不是deftype也没有defrecord为你定义任何工厂功能,但你应该自己做.完整性检查进入这些功能(和/或相应的测试).

  3. 概念上更复杂的操作当然非常适合构建在get&Co.基础上的协议功能.

哦,并gvec.clj在Clojure的源代码中deftype查看一些使用的一些严肃的数据结构代码可能看起来像的例子.这里的复杂性与您在问题中描述的内容有所不同,但它仍然是Clojure中当前可供公众使用的少数自定义数据结构编程示例之一(当然它也是优质代码).

当然,这正是我的直觉告诉我的.我不确定在这个阶段是否存在很多已确定的习语,deftype实际上并没有被释放的所有内容.:-)