Tuesday, July 15, 2008

Is Scala for Academics and Egomaniacs?

This one isn't going to be a meaty technical article nor a deep philosophical exploration. Instead it's about perception vs reality. What moves me to post is the following 3 twits from Tim Dysinger.

Edit: A few more

Edit 2: One more, a blog post this time
I happened to be involved in the discussion that led to his conclusions. Here's the complete, unedited log from the #scala IRC channel. I leave it to posterity to decide if there was too much academia or egomania or if the guy was kicked for arguing.

Warning:Foul Language

(09:34:37 AM) doub: how can I print the address of an object rather than the output of its toString ?
(09:35:27 AM) dysinger: ah not c++
(09:35:32 AM) dysinger: it's java
(09:36:02 AM) dysinger: the default toString implies there is an address available
(09:36:04 AM) paulp: what is this "address" you speak of
(09:36:21 AM) paulp: you're harshing my abstraction mellow
(09:36:32 AM) doub: anything that could let me distinguish two distinct objects that have the same contenty
(09:36:34 AM) doub: *content
(09:36:43 AM) JamesIry: .equals
(09:36:45 AM) paulp: hashCode?
(09:36:49 AM) JamesIry: oops, .eq I mean
(09:36:49 AM) dysinger: Not even via JNI. JNI doesn't hand out objects' addresses, only "handles" that
(09:36:49 AM) dysinger: can be used to refer to them.
(09:37:05 AM) dysinger: hashCode is what you want.
(09:37:30 AM) doub: i have one object now, and one object later, and i want to know if that's the same or not, and i'd rather not store a reference to the first until i get the second
(09:37:37 AM) JamesIry: It's not what he wants. It's overridable and not guaranteed unique
(09:37:51 AM) dysinger: you should over-ride equals and hashCode if you want to compare content
(09:37:55 AM) DRMacIver: System.identityHashCode will give you the system version though
(09:37:58 AM) ijuma: hashCode is not necessarily good enough because it's an int and you may be running a 64-bit machine
(09:38:23 AM) ijuma: I mean System.identityHashCode above
(09:38:25 AM) dysinger: ^ the default impl you mean
(09:38:54 AM) DRMacIver: Sure. It's not foolproof.
(09:39:13 AM) JamesIry: System.identityHashCode isn't guaranteed unique either.
(09:39:26 AM) JamesIry: Only guaranteed to always be the same for the same object
(09:39:44 AM) doub: the System in java.lang ?
(09:39:47 AM) dysinger: doub if you over-ride hashCode and equals like it says in the core javadocs, you'll have all the control you need to compare two objects of the same class.
(09:39:48 AM) DRMacIver: Why don't you want to store a reference to the first?
(09:40:36 AM) JamesIry: doub, yes, System in Java.lang
(09:42:49 AM) doub: DRMacIver: i can't clearly state my reasons, so i guess they're bad ones
(09:43:05 AM) JamesIry: doub, the only thing guaranteed to work is .eq
(09:43:47 AM) dysinger: doub if you don't want to keep a reference to a previously seen object, take a hash of the object and keep that.
(09:44:21 AM) doub: with identityHashCode ?
(09:44:38 AM) dysinger: I would just use a library because I am lazy like that
(09:44:39 AM) dysinger: http://commons.apache.org/lang/api/org/apache/commons/lang/builder/HashCodeBuilder.html
(09:44:41 AM) lambdabot: Title: HashCodeBuilder (Lang 2.3 API), http://tinyurl.com/5639k7
09:45
(09:45:08 AM) dysinger: http://commons.apache.org/lang/api/org/apache/commons/lang/builder/EqualsBuilder.html
(09:45:10 AM) lambdabot: Title: EqualsBuilder (Lang 2.3 API), http://tinyurl.com/5n3wyz
(09:45:18 AM) doub: isn't there something low level in the jvm itself that can give me a unique string for an object ?
(09:45:36 AM) dysinger: hashCode is ok
(09:45:43 AM) JamesIry: Everybody please stop suggesting hash codes, identityHashCode or not. There is no guarantee that objects with unique identity will have unique hash codes.
(09:46:15 AM) dysinger: ah lol
(09:46:25 AM) dysinger: there is if I have the keyboard.
(09:46:50 AM) JamesIry: Read the spec for identityHashCode
(09:47:18 AM) JamesIry: It says not one word about uniqueness guarantees. A perfectly legal JVM could return 0 everytime the method is called.
(09:47:48 AM) dysinger: jameslry read the docs on equals and hashCode -> one of the fundementals of java.
(09:48:08 AM) dysinger: you don't just "use" them - you over-ride them.
(09:48:13 AM) DRMacIver: It's appropriate that "one of the fundamentals of java" is fundamentally broken. :)
(09:48:15 AM) JamesIry: equals -> same hash code, not the other way around
(09:48:47 AM) JamesIry: You can write your own hashCode to always return 0 and it will obey that contract
(09:48:55 AM) JamesIry: It would be stupid, but it would be "legal"
(09:49:17 AM) dysinger: lol what are you smoking ?
(09:49:42 AM) dysinger: omg - same shit different day - it's a formula - #1 hang out, #2 bash java/ruby/perl/etc, #3 don't actually know any java.
(09:49:51 AM) DRMacIver: It's a really powerful drug called "Knowing what you're talking about". :)
(09:50:01 AM) ijuma: dysinger: you are not paying attention to the discussion
(09:50:02 AM) JamesIry: Here's a proof. There are 2^32 unique ints. How many unique strings are there? Infinitely many. Ergo, there must be a possibility of collision.
(09:51:24 AM) ijuma: JamesIry: btw, there's a blurb in Object.hashCode about returning distinct integers for distinct objects where reasonably practical. of course, there's no guarantee, but in some cases it may be good enough.
(09:51:35 AM) ijuma: (the native Object.hashCode implementation that is)
(09:51:46 AM) JamesIry: ijuma: I agree, if you control the JVM it may very well be enough to use identityHashCode
(09:52:00 AM) JamesIry: But just using .eq is far more robust and guaranteed to work in the future.
(09:52:00 AM) dysinger: There is theoretically a possibility of a collision in the RFC for UUID too. It doesn't paralyze anybody except academics that don't actually code but stand around and debate edge cases.
(09:52:16 AM) JamesIry: dysinger, please read the original requirement
(09:52:24 AM) dysinger: please pontificate
(09:52:25 AM) ijuma: JamesIry: yeap, agreed
(09:52:40 AM) dysinger: I did read the original
(09:52:51 AM) JamesIry: doub wanted to know when he got the same (as in identity) object twice
(09:53:00 AM) dysinger: yep
(09:53:12 AM) dysinger: which can be handled perfectly by over-riding equals and hashCode
(09:53:18 AM) JamesIry: No!
(09:53:21 AM) ijuma: lol
(09:53:28 AM) JamesIry: Same identity, not content
(09:53:42 AM) ijuma: communication is hard sometimes
(09:53:54 AM) DRMacIver: It's not like this is a weird theoretical possibility which never crops up.
(09:53:54 AM) dysinger: over-riding those gives you any amount of comparison you want.
(09:54:01 AM) DRMacIver: scala> "\0".hashCode == "".hashCode
(09:54:01 AM) DRMacIver: res1: Boolean = true
(09:54:31 AM) dysinger: he didn't say I have random objects of different classes coming through
(09:54:52 AM) DRMacIver: Strings are not a particularly random choice. :)
(09:54:57 AM) ppohja: DRMacIver: you evil academic, standing around and finding just the corner cases :)
(09:55:05 AM) JamesIry: dysinger, why would you want to override equals to do a job when there's already a perfectly good .eq (or Java ==) method/operator that does the job?
(09:55:15 AM) JamesIry: Seriously, why?
(09:55:49 AM) JamesIry: Override equals when you want a non-identity based comparison. Override hashCode to be consistent. But when you want identity, there are tools built in to Java
(09:55:50 AM) DRMacIver: ppohja: It's amazing how often I genuinely get accused of being an academic in programming related discussions. I find it really funny. :)
(09:55:52 AM) JamesIry: or Scala
(09:55:54 AM) dysinger: because the default equals does not compare conntent.
(09:55:55 AM) dysinger: content
(09:55:59 AM) dysinger: it compares hashCodes
(09:56:12 AM) JamesIry: dysinger, no it compares identity, which is what doub was talking about
(09:56:22 AM) doub: given my system it would take some time to implement a storing mechanism for reference to past objects and comparisons with the new ones
(09:57:03 AM) doub: just printing the hash gave me a very loose but still usefull information about my object, and took less time than the conversation about my question :-)
(09:57:08 AM) dysinger: jameslry the default java equals compares the class and the hash code giving you identity
(09:57:08 AM) JamesIry: doub, stick 'em in an IdentityHashMap
(09:57:24 AM) doub: but I agree with all you said JamesIry, and I would use .eq for a production system
(09:57:36 AM) JamesIry: dysinger, no the contract just says identity. hashCode is not part of the contract.
(09:58:08 AM) DRMacIver: That would be a pretty stupid implementation when you can just compare the addresses of the objects...
(09:58:10 AM) JamesIry: The fact that a particular jvm uses an object's unique handle as a hashCode is an implementation detail
(09:58:37 AM) JamesIry: DRMacIver: except that internally a JVM can use 64 bit addresses
(09:58:51 AM) DRMacIver: Hm. Why is that a problem?
(09:59:09 AM) JamesIry: DRMacIver: sorry, I misunderstood you
(09:59:42 AM) JamesIry: DRMacIver: you're right, a JVM should compare addresses (or handles or something). It MAY base identityHashCode on that address or handle or whatever, and most probably do.
10:00
(10:00:00 AM) DRMacIver: I think hotspot uses the address in the lock table for hashCode
(10:00:19 AM) DRMacIver: Wouldn't swear to it though
(10:00:36 AM) dysinger: jameslry - if you have been on java very long you would know that the defaul equals uses class and hash code.
(10:00:39 AM) DRMacIver: (It definitely doesn't use the object's address, as that will change on a fairly regular basis)
(10:00:55 AM) dysinger: and that anytime you over-ride one of those methods - you over-ride both.
(10:00:59 AM) doub: would that be too restricting to require the jvm to expose a unique id per object (independent from the hash mechanism) ? like the address of some underlying memory structure
(10:01:11 AM) doub: is the JVM GC allowed to move objects in memory ?
(10:01:16 AM) dysinger: and that unless the universe explodes tomorrow - you will probably do just fine.
(10:01:33 AM) dysinger: doub - the vm moves shit all the time as needed.
(10:01:42 AM) DRMacIver: doub: Very much so.
(10:03:49 AM) DRMacIver: To the second part. The first part, probably not. But you'd have to account for the fact that collisions can still occur due to address reuse between GC cycles.
(10:04:19 AM) JamesIry: dysinger please point me to the line in the JLS that says that "==" uses class and hashCode. There's no need for us to argue. Just point it out to me.
(10:04:33 AM) dysinger: I said equals
(10:04:36 AM) dysinger: I never typed ==
(10:04:41 AM) JamesIry: The default equals is based on ==
(10:04:44 AM) dysinger: lol
(10:04:54 AM) DRMacIver: So the only guarantee you could get would be that if x and y are both live then address(x) == address(y) implies x == y. If you saw x and y at a different point in time you wouldn't be able to guarantee that same address meant x == y
(10:05:05 AM) dysinger: this is what I am talking about
(10:05:14 AM) dysinger: academic arguing
(10:05:24 AM) ijuma: interesting, it seems like once you call identityHashCode, it's computed once and then stored in the mark word
(10:05:37 AM) JamesIry: From the doc: The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value
(10:05:42 AM) ppohja: dysinger, no, it's that you're offering the wrong solution to the original problem.
(10:05:43 AM) dysinger: java has been around a dozen years with no one running away screaming from having been burned from hashCode and equals.
(10:05:45 AM) ijuma: for HotSpot, that is
(10:06:07 AM) ijuma: derived from the following statement, "Finally, there's not currently space in the mark word to support both an identity hashCode() value as well as the thread ID needed for the biased locking encoding. Given that, you can avoid biased locking on a per-object basis by calling System.identityHashCode(o)."
(10:06:31 AM) dysinger: ppohja - what's the "right" sollution in scala ? seems like we have been discussing this for 30 minutes.
(10:06:45 AM) dysinger: I know java like the back my hand.
(10:06:48 AM) JamesIry: ppohja: .eq is semantically the same as Java's "=="
(10:06:55 AM) JamesIry: I mean dysinger
(10:07:04 AM) dysinger: in scala - ok
(10:07:16 AM) JamesIry: Scala's "a eq b" translates to Java's "a == b"
(10:08:44 AM) JamesIry: Also from the doc: As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)
(10:09:10 AM) JamesIry: Note the caveat: this implementation technique is not required by the JavaTM programming language.
(10:09:30 AM) DRMacIver: So, just for the record, I looked up the source code for Object.equals
(10:09:49 AM) DRMacIver: public boolean equals(Object obj) {
(10:09:49 AM) DRMacIver: return (this == obj);
(10:10:11 AM) JamesIry: dysinger, have you looked at the back of your hand recently?
(10:10:12 AM) DRMacIver: dysinger: Or, in other words, you're full of shit. Kindly shut up about this now.
(10:11:49 AM) ijuma: JamesIry: Looks like he pays more attention to the front of his hand ;)
(10:11:54 AM) dysinger: fuck you guys
(10:12:12 AM) doub: do I get bad karma points for being the initiator of a conflict ?
(10:12:13 AM) dysinger: read the javadoc
(10:12:20 AM) JamesIry: I quoted the javadoc
(10:12:28 AM) dysinger: so did I
(10:12:33 AM) DRMacIver: dysinger: Sorry, but no thanks. I find idiocy a huge turnoff.
(10:12:45 AM) dysinger: nobody is trying to turn you on
(10:12:54 AM) ijuma: doub: no :)
(10:13:11 AM) dysinger: fuck you drmaciver - you and I have debated endlessly on other topics.
(10:13:24 AM) JamesIry: dysinger says: the default object.equals is based on class and hashCode. DRMacIver shows that it's based on ==. Dysinger gets mad
(10:13:34 AM) DRMacIver: Really? I dont' remember any instances.
(10:13:43 AM) dysinger: show me the code
(10:13:46 AM) DRMacIver: You probably blended into the endless sea of unwashed idiocy on the internet
(10:13:49 AM) JamesIry: DRMacIver: showed you the code
(10:14:04 AM) ppohja: DRMacIver: To me, this seems like you're talking to a eliza.
(10:14:12 AM) DRMacIver: ppohja: It does rather, doesn't it?
(10:14:17 AM) JamesIry: A troll
(10:14:26 AM) dysinger: "If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result. "
(10:14:27 AM) DRMacIver: I'm about ready to break out the banstick to be honest
(10:14:37 AM) dysinger: eat a dick egomanics
(10:14:38 AM) JamesIry: dysinger, I already says equals implies same hashcode.
(10:14:46 AM) JamesIry: Look back through there. I said that.
(10:14:47 AM) mode (+o DRMacIver ) by ChanServ
(10:14:54 AM) dysinger: there is no implies
(10:14:55 AM) ppohja: dysinger, after all these years with java, you're forgotten the difference between -> and <-> ?
(10:14:58 AM) mode (+b *!*n=tim@*.hsd1.or.comcast.net ) by DRMacIver
(10:14:58 AM) dysinger left the room (Kicked by DRMacIver (I've already told you you're not my type.)).

42 comments:

Anonymous said...

This is the _reality_ (that scala is academic) - not a perception.

I shouldn't have swore. That was bad on my part.

However, the fact remains that bad-mouthing other languages and academic discussion on obscure things like what "\0".hashCode and "".hashCode are the same by default doesn't do anything.

In reality, in _any_ language, he could have been done implementing way before we finished the conversation on the inner workings of hashCode and equals.

It was a waste of my time. I won't be back for more #scala.
I have a no asshole policy. Telling me to "shut up" when I was just having a conversation is rude and isn't the 1st time I have had that sort of cocky rude jab from young David R MacIver" Last time he said every language but Haskell sucks. And mapreduce said that his 7 year old son programs Haskell better than most enterprise java devs can code. -- nooooo! no ego there.

There is plenty of awesome on the internet without #scala and crew. Scala is destined for obscurity except for in the minds of a few who think it's the beezneez.

Anonymous said...

It's not always like that: polite helpful exchange

And, frankly, this sort of discussion or worse crops up in almost any kind of programming forum. I don't see why it's somehow caused by scala. Actually, I don't think it's even related to programming - I've seen similar discussions in the #buddhism channel where the topic was the abhidharma. I think it can happen with any technical subject.

Erik Engbrecht said...

WTF? How the was that academic? I was expecting someone complaining about an explaination of higher-kinded types or something like that... But someone complaining because they absolutely refuse the read/awknowledge the JVM spec?

Sheesh. You guys have the patience of saints.

Anonymous said...

Over-riding equals and hashCode to determine if two objects have the same content is as old as java itself.

Somewhere along the lines we got our wires crossed and a bunch of Haskell fanboys started pulling out the source to java.lang.Object (which is NOT the code for the VM, geniuses)

The facts remain that I am correct. Nobody uses the default equals or hashCode when comparing objects' content. Over-riding these two in tandom is exactly spelled out in the core javadoc and is a pattern that people have been using since Java started having a JVM and Spec.

Telling me that I don't know "shit" and to "shut up" coming from a 25-ish year old mathematician turned functional Haskell/Scala programming fan is absurd.

Anonymous said...

Holy crap, dysinger is a total numbskull. The guy is specifically asking for object identity comparison, not equality. So overriding equals, from default identity comparison to equality comparison is precisely the wrong thing to do. Scala .eq or java == (or Object.equals) is exactly the right answer. Any college grad in Java should know that.

Anonymous said...

Previous poster - you need to read - please re-read from the top. He wanted and I quote

"(09:36:32 AM) doub: anything that could let me distinguish two distinct objects that have the same content"

Two objects (any two) that you need to compare content (like he said) is over-riding equals and hashCode for object content comparison (in java at least) and that's what he said he wanted.

He goes on to say "(09:37:30 AM) doub: i have one object now, and one object later, and i want to know if that's the same or not, and i'd rather not store a reference to the first until i get the second" meaning they will always ! == each other.

== would get you the wrong answer. (duh!) because you would never be able to compare objects with the same content with different instances.

Anyhow, this is just name-calling and endless debate moved to a blog because you guys aren't man enough to debate on IRC.

Your arguments are all FAIL. Stop typing and learn some Java (which is what Scala is built on - ya think?).

James Iry said...

Tim,

Thanks for taking the time to stop by. I see now where the wires got crossed.

doub: anything that could let me distinguish two distinct objects that have the same content

Distinguish - tell apart
Distinct - different

Translation
doub: anything that could let me tell apart two different objects that have the same content.

Given that reading, doesn't Scala's .eq method (or, equivalently, Java's == operator) do the trick?

Germán said...

Ah, yes, it looks like dysinger got doub's question wrong and argued from there (I find James's interpretation to be correct).
Apart from that, it is definitely NOT TRUE, as demonstrated, that the default equals() is based on the hash code.

Anonymous said...

So in the end it's not about the code. We are all smart people. It's about abrasive personalities combined with not-so-clear communication. I didn't get the communication wrong as the last poster stated. The statements were vague made by "doub". Everything was fine until the punk channel opp starts to tell me I don't know my code. David MacIver can still bite my ass.

Code ->

// The following doesn't work - same as Java
class Demo(x: String) {}
new Demo("fail!") == new Demo("fail!")
new Demo("fail!").equals(new Demo("fail!"))
new Demo("fail!") eq new Demo("fail!")
new Demo("fail!").hashCode() + "|" + new Demo("fail!").hashCode()

// However, over-ride some methods just like I said and
// you have everything you need to discover any equality
class Demo(x: String) {
val contents = x
override def hashCode : Int = { contents.hashCode(); }
override def equals(other: Any) = other match {
case that: Demo => this.contents.equals(that.contents)
case _ => false
}
}
// oh what do you know they are equal ->
new Demo("ftw!") == new Demo("ftw!")
new Demo("ftw!").equals(new Demo("ftw!"))
new Demo("ftw!").hashCode() + "|" + new Demo("ftw!").hashCode()
// nope they aren't the same instance ->
new Demo("ftw!") eq new Demo("ftw!")

Tony Morris said...

Haha, this is classic idiocy!! I was overwhelmed by the string of amateur mistakes, one after the other.

I might weigh in with a tip for the knob head:
forall x y. x.equals(y) -> x.hashCode() == y.hashCode()

This is a true statement, notice the direction of the arrow (denoting logical implication).

This is a false statement:

forall x y. x.hashCode() == y.hashCode() -> x.equals(y)

In fact, it is not just "academically false", it is wildly false and there are a bazillion counter-examples.

Please keep the entertainment value up :)

Anonymous said...

dibblego, you post doesn't say anything more than hashCode of any arbitrary two instances could overlap. WTF?!

This just proves the point of this article. more pontificating talk and nothing of substance.

What about the problem at hand dibblego?

Idiocy indeed.

Erik Engbrecht said...

Tim - I think you're a little confused about == in Scala. It doesn't work the same way as in Java.

x == y in Scala is equivalent to x.equals(y) in Java.

x eq y in Scala is equivalent to x == y in Java.

So in your example in Scala, the expression:
new Demo("abc") == new Demo("abc")
will evaluate to true, but if you wrote it:
new Demo("abc") eq new Demo("abc")
it would evaluate to false.

Assuming programmer obey the non-enforced contract for equals and hashCode, then:
forall x,y x == y implies x.hashCode == y.hashCode
However, you cannot logically flip that around and say that the hashCodes being equal implies that the objects are equal.

Anonymous said...

Erik,

x == y in Scala is equivalent to x.equals(y) in Java.

x eq y in Scala is equivalent to x == y in Java.

Yes I can read the docs. My 2nd Demo class shows over-riding equals and hashCode. This gives you the ability to recognize the same reference with eq and the same object (contents) with equals (or ==)

The hashCode is irrelevant other than the javadoc says to keep it straight and over-ride them together.

Anonymous said...

I've made the same mistake before that dysinger did. The funny part (well, funny once I've cooled off) is that until you finally realize that you've misunderstood the question, it really feels like everyone EXCEPT you just doesn't get it.

Nowadays, that's my first clue to go back and reread things.

Erik Engbrecht said...

Tim,
You always have the ability to recognize the same reference with eq in Scala. You don't need to override equals/hashCode to do it. You only have to override them when you want to recognize the same contents with == (unless you're using case classes, in which case they are generated for you).

Anonymous said...

Erik,

You are correct. Had the question been "hey I don't care what object I have, how can I tell if it's the same reference as another val/var I have" it would have been much easier and less confusing.

Instead he worded it like he did care about the object contents (at the top). Then later that the new reference was most likely a new object and _might_ be a reference to 1st not _is_most_likely_. eq is not going to work unless the references are the same if it's the same as java's == (which by my tests it is). In that case you DO have to over-ride equals and hashCode to be able to tell if the instances are equal based on their class and contents.

The way it was worded was poor and I understood it to be by content. Then we got to talking over the top of each other. I did confuse "==" (scala) with "==" (java) a couple posts ago. I did mistakenly say that hashCode is involved with the default equals in java. My mistake - I think I read that it was at one time and it stuck.

Anyway my solution a couple posts back with hashCode and equals works just like I described and works no matter how you want to check equal. It took me a few minutes to write the scala code and probably an hour or more of this bullshit smear campaign - 10 times as long.

I think everyone gets the equals == eq hashCode issue and when to use what. We were just talking over the top of each other saying words like idiot, idiocy & stupid.

Once David said "you don't know shit" and "shut up" the conversation was over. David was having fun in the confrontation as usual. Same experience there as last time when he tried to convince me that all languages suck that aren't haskell and that 7 year olds were better programmers than most professionals - especially anything on the other end of the spectrum - heaven forbid - dynamic languages. Even this time the asshole said that I blend in with the sea of idiocy on the internet. What an asshole. I hope I get to "meet" him someday.

After I was kick from scala, James' posted this "article" here in an attempt to smear me and made sure to message me on a private channel to make sure I knew the post was here.

All in all my experience on #scala has been pretty _ghetto_ and I am not impressed. Remember guys that the community makes or breaks the project. Scala's not going to go far if the perception is that everyone using Scala is a Theo de Raadt or Linus Torvalds' asshole-clone calling everyone and everything else "ugly and stupid".

Germán said...

dysinger, it's hard to see what you mean by "the problem at hand". Your demo code looks OK but it shows nothing that anyone was arguing against. Everyone knew all along that by overriding equals() and hashCode() you redefine identity in whatever meaningful way, and you already know that that part of the argument is due to a difference in interpretations of a "vague" statement (which I still find unambiguous). So that part should be settled already.
David was rude, yeah, but there's still something about code, which is what they've been telling you: the default equals() is based on reference equality, that is, Java's ==. This is no academic arguing. Would you explicitly agree to this? (now, you say "yes", and the technical issues are settled -- I guess the personal issues won't change.)

Germán said...

Tim, please disregard entirely my previous posting, it was written before your latest showed up. Sorry.
I'm glad to see you have acknowledged that mistake. I have no idea who you are, but now I have a much better opinion of you than by reading the chat session alone, and I'm glad about that.
Peace!

James Iry said...

Gang,

In the "Links to this post" section, Erik has a nice article about System.identityHashCode. Just wanted to mention it here in case you missed it up there.

http://erikengbrecht.blogspot.com/2008/07/systemidentityhashcode.html

Anonymous said...

Nobody has it right. If you have different objects with the same content, then hashing it will generate the same results and not reveal that they are different objects... only that they have the same content.

Just confirms my opinion that all Java programmers are wingnuts.

Ricky Clarkson said...

dysinger:

I am mapreduce on that channel, and my 7 year old son does not program in Haskell. In fact, I have not decided what my unborn child will see first in terms of programming. I have some time to decide.

I suggest you slow down a bit with your judgements.

Germán said...

Steve, "nobody has it right"?
NOBODY is saying that by hashing you tell objects apart (considering dysinger interpreted the question differently and then made a mistake later corrected).
Plus, the hash will tell you the contents are the same IF implemented that way. With the default implementation (where equals() is based on ==), it isn't necessarily the case that you can tell equal contents from equal hash!

J. Suereth said...

Dysinger -

I'm on of those Java Developers who's just know learning Scala. Seems like you have a chip on your shoulder and are out to prove something.

Not only did you completely misinterpret the original question, you were adamantly arguing a point that no one was disagreeing with you. The entire conversation was them trying to pull your thought train from "he wants to test for content, therefore equals" into "he wants to test identity NOT content, therefore ==".

What's the recommended way to always implement an equals method in java?

public boolean equals(Object o) {
//Early out for identity equals
if( this == o ) { return true; }
//Then check class, then check content
}

So... I would say next time just pay attention to the actual needs of the questioner.

Anonymous said...

Hey thanks for your comments previous poster. Except, oh yeah, we weren't talking about Java so your Java code snippit is nice but it doesn't semantically change anything.

How about we stop this now it's boring?

To "mapreduce" above. It was either you or david that was bashing dynamic languages last time I was on #scala and that's when one of you made the 7 year old comment.

I did have a chip on my shoulder because of the close-mindedness of the last "debate" which was just you and david going off the deep end with language religion.

Pete Kirkham said...

If my understanding of the original question is correct, it is likely that the intention was to compare references for identity. But for some reason, the OP didn't want to hold a reference to the original object. Obviously you have to hold some information, so I'd guess that the intention was to allow the original object to be gc'd if otherwise unreachable. In that case, the solution I'd use would be to create a weak reference to the original object, and compare the referent for identity. If the second reference is the same as the weak reference's referent, then it wouldn't have been gc'd anyway - it must have been otherwise reachable; if the original object is otherwise unreachable, it will still be released.

Tony Morris said...

That wasn't mapreduce or David, that was quite possibly me (and yes, it is true). My son doesn't make the amateur mistake of confusing conditional and biconditional in a discussion. I know of a lot of "Java developers" - including yourself - who fail the most basic competency test in logic, reason and comprehension, hence the fact that a child (many others I suspect; I can only speak for my own) possesses critical thinking skills that transcend those of at least yourself is quite telling.

Auf Wiedersehen.

J. Suereth said...

Wow... I feel ashamed to have contributed more to this conversation. I apologize to both parties.

James Iry -> I feel like I would have done the same thing in your shoes, and yes the conversation could have been on #java with no problems.

Dysinger -> Relax, take a deep breath, and ignore the Brain-iacs in the Scala community. It's an intimidating community to try to be a part of with all the other smart people around you (me included in you). However there is still something for everyone to contribute, and real-life experience is valuable. I can tell from your blog that you do have a good technical background. Don't think you have to prove anything to the Scala community. I've never learned Haskell, and I don't plan to learn Haskell. I don't really care about all the programming language theory when it comes time to do my job. However, coming from Java and jumping into Scala I can see HUGE benefits already (even without a lot of the Functional Programming stuff). In fact, I even avoid using the hard-core FP so my co-workers can feel more familiarity when looking at my Scala utilities. The thing I like about using Scala is with all its power, you can operate at whatever level you're comfortable with. Just because the people on the forum come from Haskell, Erlang or XYZ doesn't mean it's the only way to code Scala. In fact, I don't think that's the best way for Scala to succeed. I'd like to challenge you to come up with a list of things the Scala community needs to do to "reach out" (i.e. market) itself to the Java Community (or Ruby Community). Point being, take all the criticism in stride. People misinterpret things, and especially in the academic world, criticism can be harsh.

In fact, I'm making this an open challenge. As I haven't set up an online infrastructure yet, all I have is my blog, so here's the challenge (sorry for using your blog James):

Make a blog entry detailing what Scala needs to do to market itself to the Java community and post a comment to my blog

Ok, sorry to take everyone's time.

Shanon McQuay said...

I'm amazed, not one person bothered to ask poor Doub WHY he wanted to compare his objects?

Seems that problem solving is out of fashion at the moment.

Ricky Clarkson said...

dysinger,

I don't personally bash dynamic languages, I think they are useful for novices and for code where runtime errors are not expensive (such as code you write only for yourself - e.g., I don't mind configuring emacs using elisp).

But for any code where runtime errors are expensive, I'm not sure why you'd like to promote them.

Anonymous said...

@dysinger: I have a no asshole policy.

Really?!

Over-riding equals and hashCode to determine if two objects have the same content is as old as java itself.

Sure, but that wasn't the question.

It's about abrasive personalities [...]

Here we agree:

lol what are you smoking?

omg - same shit different day - it's a formula - #1 hang out, #2 bash java/ruby/perl/etc, #3 don't actually know any java.

fuck you guys

eat a dick egomaniacs

Everybody reacts to "not-so-clear communication" in different ways. I, for example, prefer to understand why somebody is disagreeing with me, rather than assume they're egomaniacs.

Perhaps your opinion of yourself doesn't allow for the possibility that *you* might be the one that's wrong.

Anonymous said...

The only thing I was wrong on was that I said the default equals took hashCode into account. That was a mistake.

You do have zero tollerence for other people dave. I wish I had the chat log from our discussion before when we were talking about dynamic languages.

You have just as abrasive a personality as I have encountered on IRC. Not having any room for other's opinions on languages, saying "you don't know shit", being a smart-ass and telling some one to shut up is no different.

It was fun though. I accept your appology.

Tony Morris said...

Saying "you don't know shit" might be a suggestion to educate yourself, just a little.

Just a thought.

Anonymous said...

thank you James for posting this transcript. It was all highly amusing.

"dysinger" is obviously an invented character, but fun reading nonetheless!

Anonymous said...

The debate was stupid: (a != b) && (a.equals(b)) is the correct java way to test if two objects have distinct identity, but equivalent content, assuming you've defined equals() to match what you mean by "equivalent content". Similarly, if carefull constructed, hashCode() can tell you that you "probably" have the same content or that you definitely do not. You cannot access physical addresses of objects and wouldn't want to, since objects move around during garbage collection.

Anonymous said...

Wow. A pissing match that no one cares about. How fantastic! Either side could have handled this very differently, but sadly no one took the high road :(.

Anonymous said...

I'm not really a fan of Scala, I just just can't get used to the (IMO overuse of) abbreviations in the libraries. So, from an independent POV, I see that dysinger seems to be unused to being corrected. There was a couple of comments made to him that could have been nicer, but the overwhelming bile was clearly coming from him. Perhaps that is hard to see from his POV.

So sorry dysinger, but the problem looks almost entirely with you, not the Scala guys. Ruby/dynamic language advocates seem to have a bit of a problem with this sort of arrogance in their midst, and I'm afraid you rather enforce that stereotype.

Anonymous said...

It's unbelievable. If you do not understand the difference between object identity and object equality and the meaning of hashcode how can one program in Java or any other language? This understanding is so fundamental to programming, I can't believe how someone can call it academic. Would you call it academic to know how to turn on your computer either? Anyway: The one how yells first "fuck you ..." shouldn't complain about being treated rude.
By the way: "Read the fucking manual" is still true. And if this doesn't help, peek into the code itself. Java class implementations are available so feel free to take a look.
Have a nice day.

Anonymous said...

Wonder how long before XKCD makes a comment on this! What a marvelous waste of time. Just think, without dysinger's efforts, this epic would never have come to be!

egervari said...

I have to say, they told the answer really fast, you just didn't read it. It is the .eq() method.

And you didn't figure this out... how? I know scala really well, but I knew this very early on.

You can't just bash a language because you don't know it, especially a language that has a learning curve attacked to it.

And this thing you asked... I wouldn't say this should be a big part of your learning curve. If it is, go back to using php.

truth_machine said...

"The only thing I was wrong on was that I said the default equals took hashCode into account. "

You were wrong about absolutely everything, including knowing Java like the back of your hand. It's two years later -- I wonder if you're still such a pathetic cretin.

betterthanaverage said...

I have been programming for a loooong time and I just started learning Scala and my immediate impression is that no one who designed Scala had much real-world experience. Everything he said about overriding equals and hashcode is correct to a tee as far as Java in practical application is concerned. The question originally stated by doub does not sound, to my Java-encrusted ears, ambiguous at all. It is plainly obvious that the answer that dysinger gave is the one he was looking for. I think, in this convo, that dysinger was being a jackass, but I don't think he deserved to get kicked, and the arguments against him are based purely on esoteric academic fringe cases.

Tony Stark said...

"If I had an hour to solve a problem and my life depended on the solution, I would spend the first 55 minutes determining the proper question to ask, for once I know the proper question, I could solve the problem in less than five minutes."

I thought the quote was more than appropriate for the above conversation.