我应该在Clojure中实现Seq接口吗?

6

我在Clojure中有一个数据结构,代表了一组实验结果:

(defprotocol ResultSet
  (columns [rs] "return a collection of the columns in the resultset, represented by keywords")
  (rows [rs] [rs column-keys] "returns a seq of the rows in the resultset, order and column specified as keywords by column-keys. with a single argument returns rows with all columns present"))

我有一个deftype实现了这个协议。我想编写一些函数,比如在结果集中映射一个函数,或者对结果集进行折叠,基本上做与内置的序列函数相同的事情。

在Haskell中,我会通过实现相关的类型类(例如Functor),然后使用像fmap或mfilter这样的函数来完成。因此,我研究了在Clojure中如何实现这一点,最终想到了实现ISeq接口的一些想法。

那么,这是一个好主意吗?我找不到很多关于实现ISeq的资源,我想知道这种做法的惯用方式是什么。

2个回答

5
据我所知,实现这样功能的“最佳”方法不是实现 ISeq,而是 clojure.lang.Seqable; 也就是说,提供一个 (.seq) 的实现方式,将你的 ResultSet 映射为一个(可能是惰性的)序列。这是 Clojure 在大多数(所有?)集合中使用的路线,除了 List(List 实现了 ISeq,因为 seq API 已经是 List API 的子集)。

这将允许我执行类似于返回结果集中行的基础序列的操作,但它不允许我映射一个函数到“Results”并返回一个“Results”,对吗?编辑:我刚意识到内置的map函数不会像这样工作,也许我正在尝试做错误的事情。 - Alex jg
1
正如你在编辑中所说的,Clojure序列函数通常会在提供的集合上调用(seq),然后处理并返回seqs,而不是特定类型的集合。起初可能有点不直观,但实际应用效果非常好。当你真正需要时,你只需要一种将seq转换回你需要的集合类型的方法(一旦你开始处理seqs,你真正需要它的次数并不多 - 也许值得考虑是否真的需要ResultSet类型)。 - Joost Diepenmaat

0

我觉得我可能误解了你的问题,但是你不会只是使用map函数将一个函数应用于结果中的每个元素吗。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接