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

欢迎!请参阅关于页面,了解更多此工作的信息。

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进行应对似乎是一个可行的选择,但同样,如果函数同时被规范为接收和返回集合,这也将破坏data.diff。
1. 保持现状,我们将会继续让新的和老用户都感到惊讶。

这个问题存在的证据
1. 如上所述的票据似乎表明,人们经常遇到此类问题,以至于要张贴问题
1. https://docs.clojure.org/clojure.set/superset_q#example-5b5acd38e4b00ac801ed9e39

5 答案

0

评论者:alexmiller

在考虑此工单之前,需要

  • 一个良好的问题陈述
  • 评估现有代码在非集合上调用这些函数的情况
  • 一张表格,列出了替代方案及其权衡。假设替代方案包括:添加规格、添加验证检查、添加转换等。权衡可能包括对现有调用者(已知或未知)的影响、性能等。

决策事项

  • 现有的调用(具有非集合的输入)是否有效或无效?
  • 应该在函数中进行哪些更改?

在这些事情决定之前,补丁可能并不特别有用。

0

评论者:borkdude

Andy Fingerhut 的存储库中的一些有趣数据,对比了具有先决条件(无转换)的

  • 版本与经过计时的集合函数的性能
  • 仪表化集合函数

具有先决条件的函数比经过计时的函数快得多,但并不比原始函数慢多少。

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

0

评论者:stu

spec 测试可以比较输入和输出,而不会破坏任何现有代码。

0
_评论者:jwr_

我将在这里尝试第一步(最小步骤)。由于集合函数的文档字符串以 "返回一个集合" 开头,人们可以合理地期望它们始终返回集合。

我遇到的具体情况是 `(clojure.set/difference nil #{1})` 返回 nil。nil 出现的原因是因为可选项:执行了集合操作,源数据在映射中的可选项。数据通过 spec 验证(因为键是可选的),然后由于 set/difference 返回的 nil 而触发了其他验证。我意识到论点是错误的,并且我不一定期望自动转换。

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

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

鉴于文档字符串的内容,我并不认为有代码依赖于集合函数返回的不是集合。

只有编译时启用断言,后置条件的性能影响才会存在。

我明白这并没有解决提及的所有问题,但这可能是一个向前迈进的方法。

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