I'm the reporter of the mentioned ticket and I'm no longer inclined into fixing the hash. The real issue seems to lay in the fact that the = equality tries to work with host non-values. Whether the usefulness of such interoperability outweights the correctness of the =/hash is the issue which should be more discussed, with real examples.
So for me, the option a) is not the way we should go, and I would like to add an option c), to introduce a strict variant of = operation alongside the current one, and use it in cases where the =/hash inconsistency causes real trouble. Jozef On Sunday, May 11, 2014 9:06:15 PM UTC+2, Mikera wrote: > > OK..... this thread is a bit worrying. If I understand correctly, it means > that we've now got inconsistent hash and equals functions. I suspect this > hasn't bitten many people yet simply because it is unusual to mix Java and > Clojure collections as keys in the same structure, but it seems like a > really nasty issue. > > Hash and equality functions generally have a very simple rule: if two > things are equal they must have the same hashcode. But now we've got: > > (= (java.util.ArrayList. [1 2]) [1 2]) > => true > > (hash (java.util.ArrayList. [1 2])) > => 994 > > (hash [1 2]) > => 156247261 > > I consider this a major defect. If we want to define our own equals and > hashcode that's fine, but then these functions absolutely should be > consistent with each other. > > If it is really true that non-Clojure collections aren't considered as > values and aren't expected to participate in hash/= comparisons then I'd > expect an exception, not an erroneous value. Silent potential corruption of > data is *much* worse than a noisy failure. But I think even that is a bad > direction to go: easy Java ecosystem interop is definitely one of the main > reasons why I'm using Clojure, and I'd like to see this maintained. > > I can think of only two sensible ways to fix this inconsistency: > a) Roll back the hash changes. Correctness is much more important than a > performance edge case. (I suspect the hash changes have hurt average case > performance anyway...) > b) Make (= (java.util.ArrayList. [1 2]) [1 2]) and similar comparisons > evaluate to false (on the grounds that ArrayLists aren't Clojure > collections, so should not be considered equal). > > On Saturday, 10 May 2014 15:51:24 UTC+1, John Hume wrote: >> >> Thanks for the ticket pointer. I didn't find it in my initial search >> because it "Affects Version/s: None" :-/, and I knew this behavior was new >> to 1.6. >> >> For those not up for the medium-length comment-thread read: >> non-Clojure-aware Java Collections Framework interface instances are not >> considered values,* and 'Rich says "all bets should be off for >> hasheq/equiv of non-values."' That's a bit down in the details, but I >> think the upshot is that they're not currently supported as set members or >> hash keys. Unfortunately they used to be supported (unintentionally, I >> guess) due to Clojure following Java's lead, so I have some interop-heavy >> code to review and test very carefully. Though the above seems to frame >> non-support as based on principle, it seems the driver is keeping the new >> hasheq stuff highly performant. I would hope a performant implementation >> that supported the Collections interfaces would be accepted for some future >> version. >> >> *If there is one, I'd like to read a clear definition of what "values" >> means in Clojure. The headings on http://clojure.org/data_structures are >> almost an enumeration of them, except the "Collections" section talks a >> little about Java Collections classes, hashCode, and hasheq without making >> it clear that non-Clojure collections are not values. Unfortunately the >> current definition seems to admit only the Java primitives and >> near-primitives (String and primitive wrappers) and clojure-aware types. >> >> What "not supported" looks like via maps: >> user> *clojure-version* >> {:major 1, :minor 6, :incremental 0, :qualifier nil} >> user> (hash-map [1 2] "v" (java.util.ArrayList. [1 2]) "a") >> {[1 2] "a", [1 2] "v"} >> user> {[1 2] "v" (java.util.ArrayList. [1 2]) "a"} >> IllegalArgumentException Duplicate key: [1 2] >> clojure.lang.PersistentArrayMap.createWithCheck >> (PersistentArrayMap.java:70) >> user> (-> {} (assoc [1 2] "v") (assoc (java.util.ArrayList. [1 2]) "a")) >> {[1 2] "a"} >> >> >> On Friday, May 9, 2014 6:34:26 PM UTC-5, Andy Fingerhut wrote: >>> >>> Mike is correct. This change in behavior is due to the hashing changes >>> in Clojure 1.6. See the comments on ticket >>> http://dev.clojure.org/jira/browse/CLJ-1372<http://www.google.com/url?q=http%3A%2F%2Fdev.clojure.org%2Fjira%2Fbrowse%2FCLJ-1372&sa=D&sntz=1&usg=AFQjCNG6I-rrRfAMsUZUomYEbGOJkJqWGA>for >>> some discussion of whether this is considered a bug. It appears that >>> perhaps the hash consistency is not promised for mutable objects, only >>> immutable ones. >>> >>> Below are a couple more REPL transcripts that illustrate the change in >>> behavior: >>> >>> user=> *clojure-version* >>> {:major 1, :minor 5, :incremental 1, :qualifier nil} >>> user=> (= [1 2] (java.util.ArrayList. [1 2])) >>> true >>> user=> (map hash [ [1 2] (java.util.ArrayList. [1 2]) ]) >>> (994 994) >>> user=> (hash-map [1 2] "vec" (java.util.ArrayList. [1 2]) "alist") >>> {[1 2] "alist"} >>> >>> >>> >>> user=> *clojure-version* >>> {:major 1, :minor 6, :incremental 0, :qualifier nil} >>> user=> (= [1 2] (java.util.ArrayList. [1 2])) >>> true >>> user=> (map hash [ [1 2] (java.util.ArrayList. [1 2]) ]) >>> (156247261 994) >>> user=> (hash-map [1 2] "vec" (java.util.ArrayList. [1 2]) "alist") >>> {[1 2] "alist", [1 2] "vec"} >>> >>> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.