已有多个工单提出建议,clojure.set 命名空间中的一些函数在接收到非集合作为参数时可能会抛出异常,因为这些函数在某些情况下可能会返回未预料到的值。以下列表是一个样本,并非完整:CLJ-810、CLJ-1682、CLJ-1953、CLJ-1954
现在 clojure.spec 存在,可以更精确地记录这些函数的期望参数类型。这些规范可以用于在测试期间动态检测传给这些函数的错误参数类型,以及未来在 clojure.spec 之上构建的任何其他方式。
Alex Miller 在 Slack 讨论中建议,如果贡献者能帮助实现 Clojure 内部函数的此类规范,可能会很有帮助。
建议的补丁中采用的方法只是指定 clojure.set/subset?、superset?、union、intersection 和 difference 的 :args 参数必须都是集合,并指定前两个函数的 :ret 类型为布尔值,最后三个函数的类型为集合。这似乎与之前拒绝的更改这些函数行为的工单中给出的所有已知评论相匹配。
补丁: CLJ-2287-add-clojure-set-specs-v1.patch
未在上述补丁中采用的方法是允许将 nil 作为参数和返回值,但不确定这是否是这些函数预期契约的一部分,或者只是它们当前实现的一个偶然方面。
(Andy Fingerhut)检查了所有的 Clojure 和 contrib 项目中 clojure.set/union、difference、intersection、superset? 和 subset? 的出现情况,只找到了一个这样的调用来确定它没有将集合传递给它。这是在 clojure.data/diff 中的那个,这个工单上有可以修复此错误(假设它是一个错误)的补丁:CLJ-1087
我可以在几秒钟内确定许多此类调用始终传递集合(例如,因为参数被包裹在 (set ...) 调用中)。在很小一部分中,我放弃了在一分钟内弄清楚答案的尝试,因为从代码审查中完全确定答案需要回到调用树的一定高度。
请提出任何其他评估这些更改的方法,以增加您对其正确的信心。