2024年Clojure调查问卷中分享您的想法!

欢迎!请查阅关于页面以获取更多关于如何使用本站的信息。

0
Clojure

有多个工单与以下事实相关:即当传入非集合参数时,clojure.set中的集合函数会表现异常。

这些问题包括 CLJ-810、CLJ-1087、CLJ-1682 和 CLJ-1954

受到影响的函数包括

  1. difference
  2. intersection
  3. union
  4. subset?
  5. superset?

因为这些函数在传入非集合参数时会产生意外的结果。

问题
如上述问题所述,这些函数当前实现导致用户在使用非集合参数调用时产生混淆和错误结果。用户没有得到任何警告或错误指示。

可能的解决方案
1. 在这些函数的参数上添加到{{set}}的强制转换
1. 当参数不是集合时抛出异常
1. 使用clojure.spec处理这个问题
1. 保持现状

权衡
1. 鉴于CLJ-2362,它对调用{{set}}的效果接近于空操作,强制转换不应该带来太大的性能损失。有人认为代码甚至可能会更快,因为可以提供类型提示,编译器/jit可能会做出更好的选择。对于常见的错误(如将向量/列表传递给集合而不是集合)应该具有向后兼容性
1. 在非集合参数上抛出异常会破坏现在正确运行的程序(尽管是偶然的),如data.diff。
1. 使用clojure.spec处理这个问题似乎是一种可行的选择,但如果函数被spec指定为接收和返回集合,这也会破坏data.diff。
1. 保持现状,我们将会继续令新和旧的Clojurists感到惊讶。

这个问题为证据
1. 上述工单似乎表明,人们经常会遇到这个问题,并会提交工单
1. https://docs.clojure.org/clojure.set/superset_q#example-5b5acd38e4b00ac801ed9e39

5 个回答

0

评论由:alexmiller

在考虑之前,此工单需要

  • 良好的问题描述
  • 评估现有代码以与其他类型的集合调用这些函数
  • 替代方案及其权衡的表。预期替代方案包括:添加规范、添加验证检查、添加强制转换等。权衡可能包括对现有调用者(已知或未知)的影响、性能等。

需要做出的决策

  • 现有调用(具有非集合类型的输入)是有效还是无效?
  • 函数中应做出什么更改

在决定那些事情之前,补丁可能不是非常有用。

0
通过

评论由:borkdude

Andrea Fingerhut的回购有趣的数据,比较了具有预处理条件(无强制转换)和工具化集合函数

  • 的版本性能
  • 集函数

具有预处理条件的函数比后者快得多,但比原始版本慢不了多少。

https://github.com/jafingerhut/funjible#wait-isnt-this-what-clojurespec-is-for

0
通过

评论由:stu

规范测试可以比较输入和输出,而不破坏现有代码。

0
通过
评论由:jwr_

我将在这里尝试第一步(最小步骤)。由于集合函数的文档字符串以“返回一个集合”开始,因此可以合理地期望它们始终返回一个集合并不需要自动转换。

我遇到的特定情况是`(clojure.set/difference nil #{1})`返回nil。nil出现的原因是可选性:在一个集合操作中,源数据是可选的(在map中)。数据通过了规范验证(因为键是可选的),然后是因为由set/difference返回的nil违反了其他验证。

我所期望的是在包含断言编译的代码中出现的后置条件错误。

具体来说,我认为集合函数上的`{:post [(set? %)]}`后置条件是可以讨论的内容。它不涉及强制转换,它避免了讨论有效参数,只是根据文档对返回值施加了限制。

鉴于这些文档字符串所说,我不认为现有的代码依赖于设置函数返回任何其他类型的数据。

后置条件的性能影响只有在包含断言编译时才会出现。

我意识到这没有解决所有提到的问题,但这可能是一个前进的方法。

我认为这不是目前标记的“重大”问题。
0
参考: https://clojure.atlassian.net/browse/CLJ-2433(由 slipset 报告)
...