3

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

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

  1. 实际实现conj,例如,在我的数据类型的协议中,或者
  2. 实现 Rich Hickeyclojure.lang.IPersistentSet或类似的接口。

第一个似乎更容易,但也更容易弄乱函数的语义。第二个似乎我正在实现一个从未打算成为公共 API 一部分的接口,并且与该接口(协议)相关联的实际方法令人困惑地不同。例如,似乎为了conj用我的集合实现,我必须实现一个具有不同名称的cons方法。clojure.lang.IPersistentSet似乎几乎没有关于这一切如何工作的文档,这对实施这个排名集提出了很大的挑战。

我应该选择哪一个?我应该实现自己的方法还是clojure.lang接口的方法?如果我应该做后者,哪里有一些好的文档可以指导我完成整个过程?

编辑:我想明确表示我正在尝试创建一个集合,您可以通过指定元素的等级(例如,“给我第 5 个元素,先生。放。”)。据我所知,clojure 中还没有这样的集合。

4

1 回答 1

4

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

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

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


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

于 2013-09-21T00:10:20.367 回答