Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by
user> (let [h (HashMap.)]
       (.put h 1 2)
       (let [p1 (first h)
             p2 (first {1 2})]
        (println (.hashCode p1) (.hashCode p2)
                 (= p1 p2) (= p2 p1)
                 (.equals p1 p2) (.equals p2 p1))))

3 994 false false true false

clojure.lang.MapEntry does not follow the contracts of hashCode or equals for java.util.Map$Entry.  This, among other things, leads to the above non-reflexive behavior of .equals.  

I realize this isn't a simple bug; it's a fundamental issue, in that it's impossible to consistently implement both java.util.List and java.util.Map$Entry, which clojure.lang.MapEntry claims to do.  On balance I do find it very useful that Clojure map entries are equivalent to vectors, and probably wouldn't want to give that up.  But, I think that at minimum this wart should be documented somewhere, since it could lead to some very strange and hard to catch bugs.

4 Answers

0 votes
by

Comment made by: jawolfe

This might be fixable by changing seq to promise a sequence of pairs rather than MapEntries. I don't know enough about Clojure internals to know if this would entail too large a performance hit, but perhaps it's worth considering.

0 votes
by

Comment made by: stu

Rich: is there a doc patch you would want for this?

0 votes
by

Comment made by: richhickey

doc patch ok

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-750 (reported by jawolfe)
...