Using the structNew() and structClear() functions

Posted on Monday, November 15th, 2010 at 7:15 am

While the structNew() and structClear() functions do relatively the same thing, one thing to keep in mind is that the structNew() function creates a new struct and the structClear() function clears a single existing struct and all of its instances. While this may seem obvious, the last part mentioned (all existing instances of a struct) can create some fairly weird scenarios if not careful.

Essentially, if a loop is created and in each loop a struct is created and stored in an array, structClear() cannot be used to refresh the struct on each loop without clearing all instances of the struct. What happens is on loop one, the struct is created and assigned a value. On loop two the struct is cleared and a new value is inserted and appended to the array. This is great except now you do not have two independent structs. Instead you have two instances of the same struct. The result is that clearing the struct not only empties both structs, but when the new value is assigned it is assigned to both structs. Now you have two structs that are identical (this is of course appropriate if all the structs should be identical and better form as they can all be updated much more efficiently). On the eighth loop you will have eight instances of the same struct.

What we want is a new struct with a different value for each loop. As such there does need to be something that resets or creates a new struct for each loop iteration. If not, you will end up with eight structs with every value assigned to them.

To do this you need to use the structNew() function as this will create a whole new struct independent of the struct created in the previous loop. This allows the variable assignment to change (in this case to a new struct) without effecting the previously stored struct. At this point only pin pointing the struct manually will allow it to be manipulated because we’re now working with a new struct in a new array index. To better understand let’s look at a couple examples of each instance.

Storing structs without re-assignment

<!--- set a list to loop over --->
<cfset variables.colors = "blue,red,orange" />

<!--- set an array to save color data in --->
<cfset variables.colorAry = arrayNew(1) />

<!--- set an object to contain color data --->
<cfset variables.colorObj = structNew() />

<cfset variables.indexColor = "" />

<!--- loop over the colors --->
<cfloop list="#variables.colors#" delimiters="," index="variables.indexColor">
	<!--- set a new struct inside of the color key --->
	<cfset variables.colorObj[variables.indexColor] = structNew() />

	<!--- append the new color object into the array --->
	<cfset arrayAppend(variables.colorAry, variables.colorObj) />
</cfloop>

This bit of code will continue to build into the same struct and create a new instance in each index of the array. At the end of the code we end up with the following, which is simply three instance of the same struct each containing all data. Updating the ‘variables.colorObj’ will update all three instance simultaneously since they are behind the scenes all the same object.

Struct with all data

Contains all data in all structs.

Storing structs with CLEARING re-assignment

<!--- set a list to loop over --->
<cfset variables.colors = "blue,red,orange" />

<!--- set an array to save color data in --->
<cfset variables.colorAry = arrayNew(1) />

<!--- set an object to contain color data --->
<cfset variables.colorObj = structNew() />

<cfset variables.indexColor = "" />

<!--- loop over the colors --->
<cfloop list="#variables.colors#" delimiters="," index="variables.indexColor">
	<!--- clear the struct --->
	<cfset structClear(variables.colorObj) />

	<!--- set a new struct inside of the color key --->
	<cfset variables.colorObj[variables.indexColor] = structNew() />

	<!--- append the new color object into the array --->
	<cfset arrayAppend(variables.colorAry, variables.colorObj) />
</cfloop>

Notice here the only added code is the first line inside the loop using the ‘structClear()’ function. In this case we are still creating a new instance (as opposed to a new object) for each loop. In the previous example each loop would build into every existing instance. In this example we clear every available instance. As such, the array in the end contains only a single struct in each index, but each struct contains the same value which is the last value looped over. The reason again, is that in the third loop the struct and all three instances are cleared and the last value is inserted into all three instances.

Same data in each struct.

Contains the same data in each struct.

Storing structs with NEW re-assignment

<!--- set a list to loop over --->
<cfset variables.colors = "blue,red,orange" />

<!--- set an array to save color data in --->
<cfset variables.colorAry = arrayNew(1) />

<!--- set an object to contain color data --->
<cfset variables.colorObj = structNew() />

<cfset variables.indexColor = "" />

<!--- loop over the colors --->
<cfloop list="#variables.colors#" delimiters="," index="variables.indexColor">
	<!--- create a new struct --->
	<cfset variables.colorObj = structNew() />

	<!--- set a new struct inside of the color key --->
	<cfset variables.colorObj[variables.indexColor] = structNew() />

	<!--- append the new color object into the array --->
	<cfset arrayAppend(variables.colorAry, variables.colorObj) />
</cfloop>

In this example we are simply re-assigning the variable ‘colorObj’ to hold a whole new struct. This is the solution. Since each struct is to hold a unique value each struct needs to be unique. As such the solution is to make sure that for each loop a new struct is created and that value assigned and the struct stored in the array. Once stored the variable can be safely re-assigned a new value without having to worry about effecting the recently created object. The final output should look like the following.

correct struct set.

Contains a unique struct in each index.

Tags ,
CategoryColdfusion

Leave a Reply

*
(Won't be published) *