已经创建了几个工单,建议在 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 ...) 调用中)。在很小一部分中,我放弃了在一分钟内找到答案,因为从代码检查中完全确定答案需要回溯调用树一段距离。
请提出其他可以评估这些更改的方法,以提高您相信它们是正确的信心。