按照意图和文档,clojure.set/intersection旨在在两个集合之间进行操作。然而,它有时允许(并且在对非集合参数进行正确操作后返回)非集合参数。这混淆了非集合参数不应使用的意图。
以下是一个使用Set与KeySeq的示例:
如果存在交集,您将得到一个结果。这可能导致编写此代码的人认为这是可以接受的,或者没有注意到他们已使用不兼容的数据类型。然而,一旦交集为空,就会发生适当的方法错误,尽管这只是一种意外,因为clojure.core/disj的第一个参数应该是集合。
user=> (require '[clojure.set :refer [intersection]])
nil
user=> (intersection #{:key_1 :key_2} (keys {:key_1 "na"})) ; 这可以工作,但不应该
(:key_1)
user=> (intersection #{:key_1 :key_2} (keys {:key_3 "na"})) ; 这失败,因为intersection假设第二个参数是Set
ClassCastException clojure.lang.APersistentMap$KeySeq不能用clojure.lang.IPersistentSet转换为 clojure.core/disj (core.clj:1449)
(disj (keys {:key_1 "na"}) #{:key_1 :key_2}) ; intersection所做出的假设
ClassCastException clojure.lang.APersistentMap$KeySeq不能用clojure.lang.IPersistentSet转换为 clojure.core/disj (core.clj:1449)
对于一个显然为特定类型而设计的库,强制类型安全似乎是一件负责任的事情。这可以防止带bug的代码不知不觉中被接受为正确的,直到正确的数据出现以触发陷阱。