user=> (def m (sorted-map 1 2))
#'user/m
user=> (map? m)
true
user=> (get m :type)
ClassCastException java.lang.Long cannot be cast to clojure.lang.Keyword
clojure.lang.Keyword.compareTo (Keyword.java:114)
sorted-map
似乎选择了一个数字比较函数,该函数不会与关键字进行比较。
理由很好,"这个东西支持IPersistentMap。所以,我可以在其上调用get
来查明它是否是我所知道的一种地图,而不会有抛出异常的风险。" get
的文档字符串表示"如果键不存在,则返回映射到key,not-found或nil的值。"
在关键查找错误时抛出异常?更重要的是,是否有一种安全,标准的方法来检查任意对象是否属于给定的类型" (由与其:type
键关联的值定义)?
答案 0 :(得分:2)
sorted-map
的密钥在某种程度上应具有可比性似乎是合理的,1
和:type
的情况并非如此,这是异常的原因。< / p>
话虽如此,我说你应该能够使用任何类型的密钥查询地图,如果地图中提供的密钥和密钥不具有可比性,则会获得nil
。
您可以通过提供所需类型检查的sorted-map-by
提供自己的比较器来解决问题。
答案 1 :(得分:0)
这是一个发人深省的问题,我很高兴你问过它。在思考之后,我倾向于期望与其他答案中提到的相同 - 我可能希望返回nil
,但也许Rich有这样做的哲学原因。
至于问题的最后部分:您可以使用type
。如果要测试已知类型,也可以使用instance?
。我猜诀窍是类型(几乎总是我相信)将成为底层Java类
user=> (type foo)
clojure.lang.PersistentTreeMap
user=> (instance? clojure.lang.PersistentTreeMap foo)
true
编辑: 在下面的讨论中,我在这里添加了一些额外的示例代码(比评论更容易阅读)。这将允许任意元数据附加到数据结构:
user=> (def foo (sorted-map 1 2))
#'user/foo
user=> (def foo-enhanced (with-meta foo {:type :integer-keys}))
#'user/foo-enhanced
user=> foo-enhanced
{1 2}
user=> (meta foo-enhanced)
{:type :integer-keys}