Sunday 28 July 2013

OK, I'm very confused: arraySort() with a callback...?

G'day
I'm sitting at Shannon Airport awaiting my return flight to London, and killing time via Guinness and responding to comments on my blog. There are no little old catholic ladies here today to keep me bemused, indeed it's very quiet.

Anyway, this is the comment I'm currently trying to reply to:

I executed the example you have showed above for customised sorting using arraysort function, but i didn't get the same result. The output i got was the array that i defined in the code. I can't understand why its not happening for me.
 The code in question is this:


a = [
    {firstName="Witi", lastName="Ihimaera"},
    {firstName="Patricia", lastName="Grace"},
    {firstName="Alan", lastName="Duff"},
    {firstName="Lee", lastName="Tamahori"},    // OK: not an author
    {firstName="Keri", lastName="Hulme"}
];

arraySort(
    a,
    function (e1, e2){
        return compare(e1.lastName, e2.lastName) > 0;
    }
);
writeDump(a);

And back when I wrote the article, the output was this:

array
1
struct
FIRSTNAMEAlan
LASTNAMEDuff
2
struct
FIRSTNAMEPatricia
LASTNAMEGrace
3
struct
FIRSTNAMEKeri
LASTNAMEHulme
4
struct
FIRSTNAMEWiti
LASTNAMEIhimaera
5
struct
FIRSTNAMELee
LASTNAMETamahori

Note that everyone's sorted by surname, which is cool. Well: it was cool. When I run that code today, I get this:

array
1
struct
FIRSTNAMEWiti
LASTNAMEIhimaera
2
struct
FIRSTNAMEPatricia
LASTNAMEGrace
3
struct
FIRSTNAMEAlan
LASTNAMEDuff
4
struct
FIRSTNAMELee
LASTNAMETamahori
5
struct
FIRSTNAMEKeri
LASTNAMEHulme

ie: as per its initial state.

Initially I thought I had written some code and never tested it... but the dump in the original article bears out that the code did run (ie: I didn't fake it!).

Next I ran the code on Railo via cflive.net, and the code doesn't run there either. Well: it runs, but it doesn't sort anything.

My code is clearly wrong, so I googled about for other examples, and landed on Ray's blog, which had its own example:

<cfscript>
data = ["Neil Diamond","Depeche Mode","The Cure","Cher","Ace of Base","Frank Sintra", "The Church"];
 
arraySort(data, function(a,b) {
    //remove the The
    var first = a;
    var second = b;
 
    first = replace(first, "The ","");
    second = replace(second, "The ","");
 
    return first gt second;
});
 
writeDump(data);
 
</cfscript>

(This, btw, marks the only occasion Ace of Base will ever be mentioned on this blog. And that Frank Sintra bloke? Some spelling-challenged cuzzie of Old Blue Eyes, I guess ;-)

I can recall running this code, and I can recall it working. However running it today: it doesn't work.

It would seem very strange to me if we both offered up code examples for the same functionality which didn't work, so I smelled a rat.

I consulted the ColdFusion docs for arraySort(), and they were useless. They don't even mention that one can use a callback in arraySort() at all. On initial pass of the Railo docs for arraySort(), I was like "yeah, so it should work". Then I looked closer.

Here's my code:

return compare(e1.lastName, e2.lastName) > 0;

And Ray's code:
return first gt second;

And the docs:

[...] and return: -1, if first parameter is "smaller" than second parameter 0, if first parameter is equal to second parameter 1, first parameter is "bigger" than second parameter
So we should not be returning if the first is greater than the second, we should be returning the result of a compare() call: so whether the first value is less than, equal to or greater than the second one. Fair enough. And I changed the code (Ray's and mine both) and it now works on ColdFusion and Railo.

But here's the thing... it's not like Ray and I both got this wrong, and both didn't test our code, and both basically posted a load of ballocks on our blogs (well: it's not like I'm a stranger to posting a load of ballocks on my blog, but I mean not in this instance. And Ray isn't like that at all). It seems to me that ColdFusion has changed its behaviour since we wrote those blog articles. I searched the ColdFusion bug base but there's no mention of this. Nor is there any reference anywhere else that I can find. Curious. It seems to me that Adobe have snuck a "fix" in under the radar here, and didn't tell anyone about it. Which sux a bit, as it means no-one who was already using the function knew they needed to update their code.

I'm not in the position to do so now, but later on I shall roll-back my CF10 install to where it was when I wrote that original article, and see if I can work out when this change happened.

Update:
The original code works on Java 6, but not on Java 7. This does not make a huge amount of sense to me, to be honest...? I don't think I have finished looking into this.

And I shall update the code in its original location.

30min or so until boarding... that's enough time for another pint...

--
Adam