2024 Clojure 状态调查!中分享您的想法。

欢迎!请参阅关于页面以获取有关这些功能的更多详细信息。

0
Clojure
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假定第二个参数是集合
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)


对明显针对特定类型的库强制类型安全性是负责任的做法。它可以防止错误代码在不知情的情况下被认为是正确的,直到正确的数据出现踩到陷阱。

5 回答

0

评论由:jafingerhut

CLJ-810与之类似,但它是关于clojure.set/difference函数的。那个被拒绝,评论是"如果不传入集合,set/difference的行为没有文档说明。"我不知道核心团队将对这个票据做出什么判断,但想提供一些历史。

Dynalint(链接:1)和我想也许Dire(链接:2)可以用于向核心函数添加动态参数检查。

(链接:1) https://github.com/frenchy64/dynalint
(链接:2) https://github.com/MichaelDrogalis/dire

0

评论者:alexmiller

现在,由于对于集合(set)的操作速度更快,我认为我们实际上可以在以前可能不会做的地方添加对集合的检查。因此,用新的视角来看是有意义的。

0

评论者:jawolfe

回到2009年,我向集合函数提交了一个带有显式set?检查的补丁,Rich的回应是:“这些函数在第二个参数不是集合时仍然能工作只是一个实现事实,而不是接口的承诺,所以我不赞成对set?测试或对这一点的任何其他妥协。”不过,不确定这是否仍然准确。

0

评论由:jafingerhut

如果您需要一个与clojure.set函数行为相同、但它们在运行时执行您提供的参数类型检查并且如果参数类型不正确则抛出异常的现成兼容替换,请考虑使用可互换库:https://github.com/jafingerhut/funjible

0
参考: https://clojure.atlassian.net/browse/CLJ-1682 (由vhouseman报告)
...