刚刚遇到了一些关于sorted-set
的有趣行为。具体来说,对于普通set
,当元素不存在时,用户协议为nil
。然而,对于sorted-set
,如果比较器没有优雅地处理类型,调用将抛出异常。这个原因是合理的(比较器要求能够理智地比较元素),但在“非成员”的情况下接口略显困惑,因为我们知道如果类型的默认比较方式不能使用,该元素就不存在于集合中。
换句话说,我猜我建议的是,使用默认比较器的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)。
java.lang.String无法转换成class clojure.lang.Keyword(java.lang.String在模块java.base中由加载器'bootstrap'; clojure.lang.Keyword在未命名的模块中由加载器'app'加载)
`
我认为我处理这种情况的选择可能是try/catch或者编写自定义比较器,两者似乎都有点奇怪 :)
我可能遗漏了什么,但仍然觉得这很有趣 :)