如何最好地与clojure抽象集成?

时间:2013-09-20 14:42:40

标签: clojure abstraction leaky-abstraction

我在clojure中实现了一个有序集,我根据它们的排名检索元素。这意味着我可以在对数时间内检索第4个元素(根据集合的顺序),第3个或第7个元素。

为了让我的新数据结构与clojure的常用方法(或“抽象”)集成,例如conjgetnth等,这是更好的方法这样做:

  1. 实际上,例如,在我的数据类型协议或
  2. 中实现conj
  3. 实施Rich Hickey的clojure.lang.IPersistentSet或类似的界面。
  4. 第一个似乎更容易,但也更容易弄乱函数的语义。第二个似乎是我正在实现一个从未打算成为公共API的一部分的接口,并且与该接口(协议)相关联的实际方法容易混淆。例如,为了使用我的集合实现conj,我必须实现cons clojure.lang.IPersistentSet方法,该方法具有不同的名称。似乎没有关于这一切是如何工作的文档很少,这对实现这个排名集提出了很大的挑战。

    我应该选择哪一个?我应该实现自己的或clojure.lang接口的方法吗?如果我应该做后者,那么哪些好的文档可以指导我完成这些工作?

    编辑:我想说清楚我正在尝试创建一个集合,您可以通过指定元素的以对数时间检索任何元素(或“删除”它)等级(例如,“给我第5个元素,先生。”)。据我所知,clojure中还没有这样的设置。

1 个答案:

答案 0 :(得分:4)

首先,我刚刚发布了一个名为avl.clj的库,它实现了持久的有序映射和集合,支持标准的Clojure API(它们是内置排序集合的直接替换),以及瞬态和对数时间排序查询(通过clojure.core/nth 1 。支持Clojure和ClojureScript;在我的初步基准测试中,Clojure方面的性能大多与内置变体相当。如果您想试一试,请点击上面的链接。任何经验报告都将不胜感激!

至于实际问题:我担心Clojure的内部接口上没有太多文档,但是实现它们是使自定义数据结构适合内置接口的唯一方法。 core.rrb-vector(我已经编写并现在维护)采用这种方法,其他Contrib库实现各种数据结构。这也是我用avl.clj做的,以及sorted.clj(基本上是基于红黑树的已排序集合的ClojureScript端口,后向移植到Clojure)。所有这些库,以及Clojure自己的gvec.clj文件,它实现了由clojure.core/vector-of生成的原始存储向量,可以作为所涉及内容的示例。 (虽然我不得不说在这里和那里很容易错过一种方法......)

ClojureScript中的情况要简单得多,其中所有核心协议都在core.cljs的顶部定义,因此您只需查看列表并选择与您的数据结构相关的列表。希望有一天在Clojure方面也是如此。


1 目前按等级删除(disj my-set (nth my-set 123))。如果结果表明在性能方面有足够的差异,我可能会在稍后提供直接实现。 (我肯定会写一个来检查它是否确实。)