我最近遇到一些关于sorted-set
的有趣行为。例如,对于正常set
的用户合约是当元素不存在时返回nil
。但是,对于sorted-set
,如果在比较器中不优雅地处理类型,则调用会抛出异常。这个原因是合理的(比较器需要能够合理地比较元素),但是由于我们知道如果元素类型无法用默认方式进行比较,则元素不在集合中,所以在“无成员”的情况下该接口有点令人困惑。
换句话说,我猜想我建议当使用默认比较器的排序集合无法进行比较时,应该使用合理的默认行为 nil
而不是 throw
,以便允许空值 punning。
例如,在将表单传递给关键字函数 (:foobar form)
时遇到了这种情况,这允许对许多其他集合进行空值 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)在用户 eval246355 (form-init59552761865518221.clj:8123)。
类 java.lang.String 无法转换为类 clojure.lang.Keyword(java.lang.String 在启动器模块 java.base 中;clojure.lang.Keyword 在未命名的启动器模块中)
`
我想处理这一点的选择是 try/catch 或者写一个自定义比较器,但两者似乎都很诡异 :)
可能是我没注意到什么,但无论如何,这很令人感兴趣 :)