On Sat, Oct 22, 2011 at 9:48 AM, Chas Emerick <cemer...@snowtide.com> wrote:
> If Clojure's primary objective were Java interop, I might agree with you. > However, it's not, and it's bizarre to see someone argue that this is not > broken: > > user=> (.equals (Integer. -1) (Long. -1)) > false > > Sure, not broken according to the Java object model and its equality > semantics, but damn well broken if your standard is something other than > what was canonized in java.lang.Object 20 years ago. 1 == 1 all the time — > or, it should — regardless of the containers such integers incidentally find > themselves within. > >From the beginning Clojure's story has been, "why reinvent the wheel when there's this great JVM with a million man-months of engineering," and I do believe interop has been a huge objective. There are lots of existing libraries that can be used, and the whole "Clojure integers are java.lang.Integers, and Clojure Strings are java.lang.Strings" always seemed to me to be about interop and being a good, integrated citizen on the JVM. Of course I was not saying that 1 should not equal 1. I was saying that to be on the JVM you should adhere to the hashCode contract. And it's not the java.lang.Object equality semantics that are broken. The hashCode contract is a mathematical contract that you must follow if you want to implement a hash table in any language. Sure, Integer and Long seem to be weird in that they are not equal to each other when they are in the same range, but that's a problem with Integer and Long semantics, not java.lang.Object semantics. And you can't fix that problem by essentially rewriting/overriding the equals method for Integer and Long, and not also rewriting/overriding the hashCode method for those same classes. If you don't also override hashCode, then you get broken behavior as I demonstrated. Thus, Clojure's notion of equivalence, which leads to pleasantly consistent > behaviour, e.g. (== (Integer. 1) 1 1N). Which, of course, doesn't preclude > one using .equals if you truly want Java math semantics instead of = or == > (neither of which have ever been advertised as adhering to the > hashcode/.equals contract, at least since Clojure 1.0 IIRC). > Clojure PersistentHashMaps are java.util.Maps, and to whatever extend Clojure defines new types on the JVM and implements an equals method for those types, it should also implement a hashCode method that adheres to the contract. > If there are some common rough spots in the interop for certain use cases, > perhaps those can be smoothed out with a library, maybe contributed by > someone that acutely feels that pain. > I don't intend to muddle the discussion, but only to point out that there are two separate issues: 1) the way collections behave when you use Longs that are in the Integer range. This is a problem with the implementation of PersistentHashMap, and unrelated to boxing ints as Longs. Boxing ints as Longs only hides the underlying issue that PersistentHashMap should not be using the default implementation of hashCode, but it's own implementation of equals. 2) ints being boxed as Longs. When you looks a Chris Perkin's post it certainly seems broken that ints are the *only* primitive that is not boxed into its java.lang equivalent. Also, AFAICT boxing ints as Integers would have no effect on the faster numeric maths. Paul -- 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