When is a Structure not a Structure?
A few days ago I was working on an application I inherited and needed to clear a structure that was stored in the session. No problem, right? Just use StructClear(). But every time I tried, I got an "Element is undefined" error. I knew the elements were there, I could output them with no problems. But for some reason, StructClear() refused to see my structure.
Then I took a look at how the elements in the structure were being set and I discovered why. As it turns out, what I thought was a structure was actually just a bunch of individual strings, due to the way they were being created with StructInsert(). Take the following example:
<cfset variables.myVar.one = 1>
<cfset variables.myVar.two = 2>
<cfset variables.myVar.three = 3>
<cfset variables.myVar.four = 4>
<cfdump var="#variables#">
This just creates a simple structure named "myVar", which gives us the following results:
Nothing special here, this is exactly what we would expect. Now, lets try the same example using StructInsert().
<cfset StructInsert(variables.myVar, "one", "1")>
<cfset StructInsert(variables.myVar, "two", "2")>
<cfset StructInsert(variables.myVar, "three", "3")>
<cfset StructInsert(variables.myVar, "four", "4")>
<cfdump var="#variables#">
Now if we dump our structure, we get the exact same result, which is still what we expected.
But, in this particular case, the variables were being added via StructInsert() a little differently, like this:
<cfset StructInsert(variables, "myVar.one", "1")>
<cfset StructInsert(variables, "myVar.two", "2")>
<cfset StructInsert(variables, "myVar.three", "3")>
<cfset StructInsert(variables, "myVar.four", "4")>
<cfdump var="#variables#">
This time if we dump our structure, this is what we get:
Notice that our actual myVar structure is empty, and now we have four new string variables created named "myVar.one", etc... This is because in the first StructInsert() example we are specifying "variables.myVar" as the structure, and adding an element named "one". However, in the last example, instead of adding a new element to the "variables.myVar" structure, we are adding a literal string called "myVar.one" to the variables scope.
If you're not used to working with structures this may seem a little confusing, especially when in all three of the code samples above you can output #variables.myVar.one# and get the exact same result. But, in actuality, behind the scenes ColdFusion (and Railo) considers the last example as something totally different from the first two. So much so that you can actually have the two together and it won't cause a conflict:
<cfset StructInsert(variables.myVar, "one", "1")>
<cfset StructInsert(variables, "myVar.one", "1")>
<cfdump var="#variables#">
However, now it seems we have two different types of variables that are named the same thing. When we try to output #variables.myVar.one#, which one of the two does ColdFusion choose? Let's change up the previous example a little to see:
<cfset StructInsert(variables.myVar, "one", "111")>
<cfset StructInsert(variables, "myVar.one", "1")>
<cfdump var="#variables#">
<cfoutput>CF chooses: #variables.myVar.one#</cfoutput>
The answer is:


e.g. Variables.myVar.one will contain 111, while Variables["MyVar.one"] will contain 1
Why not just use struct.key = "whatever";
@Dan - I was wondering if someone was going to ask that. ;) This is some really old (CF 4'ish) code that I inherited, and some of the things in it are not exactly done the best way.
It's quite understandable that some things may have changed along the way.