This morning I ran into an amusing “bug”. I had an array of structures. Any time I altered one of the structure in the array, ALL of the structures in the array were being updated. Arrgh!
Luckily, it didn’t take me too terribly long to figure out the problem. I’ll show you the culprit now:
<cfset myArray = ArrayNew(1) /> <cfset ArraySet(myArray, 1, 10, StructNew()) />
Now, you may be asking yourself, “What’s wrong with that?” That’s a great question!! (If you’re not asking it then I assume you see the problem. Give yourself a cookie!)
The problem is that structures are passed by reference. The ArraySet method is setting each of the elements, 1 though 10, not to a new structure, but the Structure created when you execute the StructNew().
In other words, ColdFusion evaluates the values of each of the arguments being passed into ArraySet before ArraySet is called. That means your structure is created beforehand too. Thus, when ArraySet is called, because StructNew() returns a struct, a reference to the newly created structure is passed in. ArraySet then loops from through the indexes you specified and sets the value of each of them to the reference to the structure. Now, any time you change anything in any structure in the array every reference reflects the change.
This is not a bug in ColdFusion. ColdFusion is doing exactly what I told it to. My solution to the problem is either to loop over the array myself and create a structure on each iteration or to use a simple value is the initial value in the array and create a structure when it’s needed.