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

这个问题存在的证据
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 出现的原因是可选性:执行了一个集合操作,映射中的源数据是可选的。数据通过了规范验证(因为键是可选的),只在后来触发了其他验证,因为 set/difference 返回了 nil。我意识到参数不正确,并不一定期望自动强制转换。

我期望的是一个后置条件错误,它会出现在用断言编译的代码中。

具体来说,我认为对集合函数应用 `{:post [(set? %)]}` 后置条件是我们可以达成共识的一件事。它不解决强制转换的问题,避免了关于有效参数的讨论,它只是在根据文档对返回值施加限制。

根据文档字符串所述,我认为目前没有代码依赖于集合函数返回除了集合以外的其它任何内容。

后置条件的影响只有在用断言编译的情况下才会出现。

我明白这并未解决提到的问题的所有问题,但或许是一个向前推进的方法。

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