@Phillyun: Thoughts? Will this work (for larger/more complex structures) or is it dumb luck with my simple example?
Could you please give more information on how the “1st execution” and “2nd execution” outputs were generated.? Perhaps using the ‘label’ attribute to add an explanation for each dump?
Even if the hashcode of the serialized struct works, I wouldn’t trust it completely in Lucee. Not in the way you’re using it here in any case. I say this for the following reason (ignoring, for simplicity, such technical intricacies as type, overriding, and so on):
It is easy to conclude from equality of hashcodes that the corresponding objects are the same. But that can be misleading even in Java, where hashcode is native. Let alone in Lucee.
In Java, hashcode’s contract is, in pseudocode:
/* Statement 1: If obj1 and obj2 have the same state, then their corresponding hashcodes are equal */
if obj1.equals(obj2) then obj1.hashCode() == obj2.hashCode()
However, there is a logical catch. The converse of this statement is generally false:
/* Statement 2: If two hashcodes are the same, then their corresponding objects are equal : WRONG conclusion! */
if obj1.hashCode() == obj2.hashCode() then obj1.equals(obj2)
Statement 2 is wrong because two distinct object instances may have the same hashcode.
Is that the logic you have been using? If so, then you’re not 100% home and dry.
It is the inverse of statement 1 that is correct, namely:
/* Statement 3: If two hashcodes are different, then their corresponding objects are not equal : CORRECT conclusion! */
if obj1.hashCode() != obj2.hashCode() then !obj1.equals(obj2)
Hence, hashcode is a test of inequality of objects, rather than of equality. Add to that the fact that CFML is weakly-typed. Object equality in CFML becomes a much more complicated affair than in Java, where hashcode is native.
For example, if you run the following Lucee code, you will find that the hashcode of struct1 is different from that of struct2.
struct1={a=1,b=2};
struct2={a=1,b=2};
dump(var=struct1, label="struct1 is {a=1,b=2}");
dump(var=struct2, label="struct2 is {a=1,b=2}");
writeoutput("<p>");
dump(var=struct1.hashcode(), label="struct1.hashcode()");
dump(var=struct2.hashcode(), label="struct2.hashcode()");
Therefore, according to statement 3, struct1 and struct 2 are not equal.
That said, would Lucee’s objectEquals() satisfy your needs? An example:
testQuery = queryNew( "name , age" , "varchar , numeric" , { name: [ "Susi" , "Urs" ] , age: [ 20 , 24 ] } );
dump(var=testQuery, label='testQuery: queryNew( "name , age" , "varchar , numeric" , { name: [ "Susi" , "Urs" ] , age: [ 20 , 24 ] } )');
writeoutput("<p>");
testQuery1= queryNew( "name , age" , "varchar , numeric" , [ [ "Susi" , 20 ] , [ "Urs", 24 ] ]);
dump(var=testQuery1, label='testQuery1: queryNew( "name , age" , "varchar , numeric" , [ [ "Susi" , 20 ] , [ "Urs", 24 ] ])');
writeoutput("<p>");
testQuery2= queryNew( "name , age" , "varchar , numeric" , [ { name: "Susi" , age: 20 }, { name: "Urs" , age: 24 } ] );
dump(var=testQuery2, label='testQuery2: queryNew( "name , age" , "varchar , numeric" , [ { name: "Susi" , age: 20 }, { name: "Urs" , age: 24 } ] )');
writeoutput("<p>");
dump(var=objectEquals(left=testQuery, right=testQuery1), label="objectEquals(left=testQuery, right=testQuery1)");
writeoutput("<p>");
dump(var=objectEquals(left=testQuery, right=testQuery2), label="objectEquals(left=testQuery, right=testQuery2)");
writeoutput("<p>");
dump(var=objectEquals(left=testQuery1, right=testQuery2), label="objectEquals(left=testQuery1, right=testQuery2)");
System:
Lucee 5.4.1.8
Windows 10 Professional