sorted-map throws exception on failed key look-up

醉酒当歌 提交于 2019-12-04 04:19:42

问题


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)

It appears that sorted-map has chosen a numerical comparison function, which won't compare with a keyword.

It would be nice to reason, "This thing supports IPersistentMap. So, I can call get on it to find out if it's a kind of map that I know about without risk of throwing an exception." The docstring for get says "Returns the value mapped to key, not-found or nil if key not present."

Is throwing an exception on key look-up a bug? More importantly, is there a safe, standard way to check if an arbitrary object is of a given "type" (defined by the value associated with its :type key)?


回答1:


It would seem reasonable that keys to a sorted-map should be comparable in some way, which is not the case with 1 and :type, this is the cause of your exception.

Having said that I'd argue that you should be able to query a map with a key of any type and get nil if the supplied key and keys in the map are not comparable.

You can solve the problem by supplying your own comparator via sorted-map-by that does the required type checking.




回答2:


this is a thought-provoking question, i'm glad you asked it. after pondering, I would tend expect the same as was mentioned in the other answer -- i'd probably like a nil to be returned, but maybe Rich has a philosophical reason for doing it this way instead.

as for the last part of your question: you can use type. you can also use instance? if you want to test for a known type. i guess the trick is the type is (almost always i believe) going to be the underlying Java class

user=> (type foo)
clojure.lang.PersistentTreeMap

user=> (instance? clojure.lang.PersistentTreeMap foo)
true

Edit: per discussion below, I'm putting some additional example code here (easier to read than in comments). this will allow arbitrary metadata to be attached to the data structure:

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}


来源:https://stackoverflow.com/questions/37410580/sorted-map-throws-exception-on-failed-key-look-up

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!