已创建了多个工单建议,在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中的调用。针对该调用有一个补丁,可以在该工单上纠正此问题(假设它被认为是bug):CLJ-1087
我可以快速确定的大多数此类调用总是传递了集合(例如,因为参数被包装在(set ...)调用中)。在很小一部分中,我在一分钟内放弃了试图弄清楚答案,因为完全通过代码审查来确定答案需要回溯调用树很久。
请提出其他评估这些更改的方法,以增加您对这些更改正确性的信心。