最近遇到了一些关于 sorted-set
的有趣行为。具体来说,对于普通 set
,用户合约是当元素不存在时返回 nil
。然而,在 sorted-set
中,如果比较器不能优雅地处理类型,调用将会抛出错误。这个 原因 看起来很合理(比较器需要能够合理地比较元素),但接口在“无成员”情况下有些令人困惑,因为如果我们知道元素不能通过默认的比较方式进行比较,则我们知道元素不在集合中。
换句话说,我猜我提议对于使用默认比较器的排序集合,当类型不能比较时,合理的默认行为应该是 nil
而不是 throw
,以便允许 nil
-punning。
例如,当将项传递给关键字函数 (:foobar form)
时遇到了这种情况,它允许在许多其他集合上进行 nil
-punning。这里是一个小的代码片段
`
user> (def normal #{"0000"})
;; => #'user/normal
user> (def sorted-version (sorted-set "0000"))
;; => #'user/sorted-version
user> normal
;; => #{"0000"}
user> sorted-version
;; => #{"0000"}
user> (:foobar normal)
;; => nil
user> (:foobar sorted-version)
执行错误(ClassCastException)在 user/eval246355(form-init59552761865518221.clj:8123)处。
class java.lang.String 不能转换为 class clojure.lang.Keyword (java.lang.String 位于模块 java.base 的加载器 'bootstrap' 中; clojure.lang.Keyword 位于加载器 'app' 的未命名模块中)
`
我认为我处理此问题的选择是 try/catch 或编写自定义比较器,这两个选择都有些不寻常 :)
我可能遗漏了一些东西,但无论如何这很有趣 :)