Friday 18 January 2013

How cool are the Railo guys?

G'day:
Just a quick one. Check this out. I was chatting with Adam Tuttle last night about some differences we'd noted in how ColdFusion and Railo seem to implement the hashCode() method for their respective struct implementations.  Here's some code (as per the thread I link to above):



<cfscript>
one = "tahi";
two = "rua";
three = "toru";

st1= {one=one, two="rua", three=three};
st2 = structNew();
st2.three = st1.three;
st2.two = two;
st2.one = "tahi";

writeOutput("#st1.hashcode()#<br />");
writeOutput("#st2.hashcode()#<br />");
</cfscript>

On CF the hash codes are the same for each struct, implying they are equal. On Railo, they are different. Also on CF the same hash code is always returned, whereas on Railo the codes change from request to request.

I didn't really understand what was going on, but the most convenient behaviour for what Adam and I were looking at was for the hash codes to a) be the same; b) always be the same value.

So I started that thread on the mailing list to get more info before deciding what to do about it. There was some disagreement from the community as to whether this constituted an incompat between CF and Railo, as this is actually one of the under-the-hood Java methods, which aren't really part of the notional compatibility "contract" Railo attempts to maintain with ColdFusion's CFML. Fair enough.

However after some back and forth on the mailing list, someone pointed me to the "spec" for hashCode(), which says this:

hashCode() docs:
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.
And this code demonstrates a problem on Railo:

<cfscript>
one = "tahi";
two = "rua";
three = "toru";

st1= {one=one, two="rua", three=three};
st2 = structNew();
st2.three = st1.three;
st2.two = two;
st2.one = "tahi";

writeOutput("st1.equals(st2): #st1.equals(st2)#<br />");
writeOutput("st2.equals(st1): #st2.equals(st1)#<br />");
writeOutput("st1.hashCode(): #st1.hashcode()#<br />");
writeOutput("st2.hashCode(): #st2.hashcode()#<br />");
</cfscript>

Sample output:
st1.equals(st2): true
st2.equals(st1): true
st1.hashCode(): 18796902
st2.hashCode(): 4565548

As per the docs, if the objects are "equal", then the hash codes are supposed to be the same.

I mentioned this to Micha, and he agreed, and asked me to raise a bug, which I did about 10min ago.

Whilst I was raising the bug, Micha did likewise, and what's more has already fixed it.

So basically he managed to get the bug fixed before I even really raised it properly.

That is really good work.

Cheers Micha & Railo dudes. I am very impressed.

--
Adam