已经创建了几个工单,建议在某些情况下,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 ...) 调用中)。在对一小部分调用中,我放弃了在分钟后尝试弄清楚答案,因为确定答案需要回溯调用树会发现。
请提出任何其他可以评估这些更改的方法,以增加您对它们的正确性的信心。