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)
对明显针对特定类型的库执行类型安全检查似乎是负责任的。它可以防止错误代码被不知不觉地接受为正确,直到正确的数据出现以触发陷阱。