2024 年 Clojure 状况调查!分享您的想法。

欢迎!请查看关于页面,了解更多关于这个功能的信息。

+11
序列
重标记

令我惊讶的是,我发现在集合上调用 distinct 会抛出异常,例如:
(distinct #{1 2 3})

一种解决方法是首先在集合上调用 seq(distinct (seq #{1 2 3}))

然而,这似乎是不必要的仪式,因为我想得起的其他任何序列操作符 - 如 mapkeepreducefirstsome 等都会接受集合。

distinct 的文档字符串表明
> 返回去除重复元素 coll 元素的懒惰序列。

由于 (coll? #{1 2 3}) => true,这对用户来说很困惑。

关于它在 math.combinatorics 中的出现,已经有一些讨论这里这里,但并没有真正做出决定。

我建议 distinct 应该接受任何可序列的 coll。

2 答案

+2

集合已具有唯一性 - 为什么要在集合上调用distinct呢?

如果你有一个函数接受一个集合,你并不一定知道它是集合还是向量,对吗?除非你在函数体内部测试它。
我将重新措辞“我建议distinct应该支持内部集合”到“distinct应该接受任何可迭代的集合”。
Stan 是对的,我封装的函数接受所有集合,并且在我接受不同值同时保持顺序是非常重要的。我已经按照Alex的建议更新了我的问题,谢谢你们。
我想这是distinct与其他序列函数特别不同,没有接受集合。distinct的步函数使用析构来查看集合中的第一个元素;析构使用nth;而nth不与集合一起工作。(nth的文档字符串同样将参数称为"coll",但列举了允许的具体类型。)

与其深入思考修正distinct的利益与弊端,我们可以在nth本身更深入地解决这个特例。已经,nth测试了几个案例,最后一个是在有序列东西上的O(n)时间。为什么不添加另一个案例来涵盖可序列化的东西呢?与contains?不同,nth没有对暴力搜索的顾忌。并且,因为nth是析构的工具,它不会非常暴力(析构大多数时候只寻找极少数的第一个元素)而且好处将非常广泛。
这不是一个好主意。nth是用于索引或有序集合的,而集合既不是索引的也不是有序的。更好的方法是将distinct应用于输入序列以生产一个稳定逻辑视图的集合,类似于所有其他的序列函数。
0
这应该得到修复,因为transducer版本运行良好,因此表现不同。

```
(into [] (distinct) #{:a :b})
=> [:b :a]
```

常规的distinct实现选择使用解构,需要nth。

是的,我们还有一些执行函数,它们接受`coll`并在所有类型的coll上工作。
...