On Mon, May 12, 2014 at 12:15 PM, John Hume <duelin.mark...@gmail.com>wrote:
> On Sunday, May 11, 2014 6:33:25 PM UTC-5, Alex Miller wrote: > >> On Sun, May 11, 2014 at 2:06 PM, Mikera <mike.r.an...@gmail.com> 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. >>> >> >> Reports of real problems in real codebases would change my own opinion of >> the severity of this issue. >> > > Here's the real problem I feared when thinking about what was new in > Clojure 1.6, which led to the testing that led to this thread: > One of our Clojure applications has two kinds of clients. (1) Legacy Java > clients use a legacy remoting lib w/ generated, > shared-across-client-and-server Java value types as messages. Where those > have a collection, that's exposed as a java.util.List<AnotherValueType>. > (2) Newer (Clojure) clients use a lighter-weight message format that's > easily read into Clojure data structures. Clients interested in the same > data need to be aggregated, and the commonality is contained in one > java.util.List<AnotherValueType> from a message the legacy clients send. > The old code used those as map keys. > I think the general recommendation would be to not do that. :) My recommendation in Java would be the same - using mutable objects as keys in a map (where mutability changes the hashcode) is a bug waiting to happen. > The new code for Clojure clients currently builds a vector of > AnotherValueType and throws that into the same map, where, under Clojure > 1.5.1, vectors and non-Clojure Lists can play nicely together. Under > Clojure 1.6, they won't play nicely any more. > > This is an easy problem to work around by making the keys from the two > client types more similar, either vectors on both sides or non-Clojure > java.util.Lists on both sides. > IMO vectors are the only choice that makes sense here. > Luckily the change on our side is recent, and Clojure 1.6 is brand new, so > this jumped out at me as something to test well before embarking on an > upgrade, and this is a (probably) subtle bug we've avoided. > Depending on your point of view, you could also say that the use of a mutable Java collection as a key is the bug you had already incurred and it's just now biting you. :) I really am sympathetic to what you're describing, but just trying to highlight how the mutability of Java collections really is a problem when used for hashing (and this is true regardless of language). Immutability is what allows us to cache the hash code of a collection (something that cannot be done in Java or Scala due to the mutability of objects, even in immutable collections). > What primarily worries me about the new behavior is that Clojure has > always embraced the host platform, but the notion of "value" that seems to > be reified in 1.6 excludes the closest things the Java platform has to > collection values. > I really don't think anything has changed philosophically in 1.6. There is a tension between interop support for mutable objects and the immutability at the core of Clojure. We've come to a point where performance concerns are driving us a bit further in one direction. > While I agree a java.util.ArrayList is a bad value, mutability is not part > of the java.util.List contract – it's optional – and even the best > (immutable) Java collection value type one can write wouldn't be treated as > a value by Clojure 1.6 unless it also implemented some clojure.lang > interface(s) (which no sane Java lib would do). In the spirit of embracing > the host platform, I'd like to see support for Java collections as values > (and let those who mutate their value-treated Java collections deal with > the nasty consequences). > In general, Clojure treats Java collections (and arrays) as values now ... but if you do mutation, then any Clojure guarantees are off (in hashing, in STM, etc). I think that's been generally a happy compromise so far. The question is to what extent that should continue. > From the comments on the ticket ( > http://dev.clojure.org/jira/browse/CLJ-1372), particularly Alex Miller's > two longer comments from March 10th, I have the impression that there's no > principled objection to this, just the performance concern with supporting > so many types in hasheq. Does that seem right, Alex? > That's my feeling (not speaking for Rich) - I'd prefer to say without exception that equiv=true => hash=same. As I said above, I think treating Java collections as "look the other way" values has been mostly a happy compromise. It may even be that this could be supported without much of a hit. Strings, numbers, keywords, symbols, and all Clojure collections should be handled above the suggested change and that covers most common key types. Some research would need to be done on what common non-Clojure classes (hence not IHashEq implementors) fall into the final else case - java.lang.Class is one that comes to mind which is used a lot inside Clojure itself. > I'd feel much better about an open issue and agreement that Clojure is in > search of a high-performance implementation treating Java collections as > values than about clear documentation of when and why hasheq is and will > remain inconsistent w/ = and all the quirks that follow from that. (Though > since we're living w/ the inconsistency, that documentation is important.) > > Thanks. > -hume. > > -- > You received this message because you are subscribed to the Google Groups > "Clojure Dev" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure-dev+unsubscr...@googlegroups.com. > To post to this group, send email to clojure-...@googlegroups.com. > Visit this group at http://groups.google.com/group/clojure-dev. > For more options, visit https://groups.google.com/d/optout. > -- 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.