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,该规则几乎是一个无操作的调用,强制转换不应带来太大的性能损失。有人认为代码甚至可能更快,因为可以提供类型提示,编译器和jit可能会做出更好的选择。对于常见的错误(例如,将向量/列表传递而不是集合),应该具有向后兼容性
1. 对非集合参数抛出异常会破坏今天正确工作的程序(尽管可能是偶然),例如 data.diff。
1. 使用 clojure.spec 处理这个问题看起来像是一个可行的选择,但如果函数被 spec'ed 为同时接收和返回集合,则会破坏 data.diff。
1. 保持原样,我们将继续让新老 clojurists 都感到惊讶。

这个问题是问题的证据
1. 提到的工单似乎表明,人们经常会遇到这个问题,以至于会提出问题
1. https://docs.clojure.org/clojure.set/superset_q#example-5b5acd38e4b00ac801ed9e39

5 个回答

0
by

评论人:alexmiller

在考虑之前,此票据需要

  • 好的问题说明
  • 评估现有代码使用除集合之外的内容调用这些函数的情况
  • 一个列出替代方案及其权衡的表格。假设替代方案包括:添加规格说明,添加验证检查,添加强制类型转换等。权衡可能包括对现有调用者(已知的或未知的)的影响、性能等。

需要做出的决策

  • 现有的调用(带有非集合的输入)是否有效或无效?
  • 函数应作出何种更改?

在此类事物决定之前,补丁可能不太有用。

0
by

评论人:borkdude

Andy Fingerhut 的一个有趣的存储库数据,比较了具有预处理条件(无强制类型转换)的集合函数版本和仪器化集合函数的性能

  • 的版本
  • 仪器化集合函数

具有预处理条件的函数比仪器化的函数快得多,但与原始函数相差不大。

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

0
by

评论人:stu

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

0
by
评论人:jwr_

我将尝试在这里迈出第一步。由于集合函数的文档字符串以 "返回一个集合" 开头,我们合理地预期它们将始终返回一个集合。

我遇到的具体情况是 `(clojure.set/difference nil #{1})` 返回 nil。nil 出现的原因是可选性:执行了集合操作,源数据在映射中是可选的。数据通过了规范验证(因为键是可选的),后来由于 set/difference 返回的 nil 而引发了其他验证。我意识到参数不正确,并且我并不期望自动强制类型转换。

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

具体来说,我认为在集合函数上有一个 `{:后 [(set? %)]}` 后置条件是大家可以达成共识的。这不会解决强制类型转换的问题,也不会讨论有效参数是什么,它只是根据文档限制了返回值。

根据文档字符串的内容,我认为没有代码依赖于集合函数返回任何除集合之外的内容。

后置条件的性能影响仅在编译时带有断言的情况下才会出现。

我意识到这并没有解决所有提到的问题,但也许这是一个开始向前推进的方法。

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