Have you ever really given a second thought to the fact that in ColdFusion/CFML you have to loop queries, arrays, and structures in completely different ways? For example, in each of these things, we are essentially doing the same thing:
<!--- looping our query ---> <cfloop query="myQuery"> <cfset doStuff() /> </cfloop> <!--- looping our array ---> <cfloop array="#myArray#" index="i"> <cfset doStuff() /> </cfloop> <!--- or ---> <cfloop from="1" to="#ArrayLen(myArray)#" index="i"> <cfset doStuff() /> </cfloop> <!--- looping our structure ---> <cfloop collection="#myStruct#" item="i"> <cfset doStuff() /> </cfloop>
In each of these cases, we are essentially doing the same thing, that being looping a collection that contains multiple items and acting on each iteration. I have always liked the fact that the ColdFusion array can be converted to a Java iterator like this:
<cfset iterator = myArray.iterator() /> <cfloop condition="#iterator.hasNext()#"> <cfset thisIteration = iterator.next() /> <cfset doStuff() /> </cfloop>
However, given the fact that <cfloop array=”#myArray#” index=”i”> is already an abstraction, it doesn’t make sense to use this in most cases. But wouldn’t it be cool if you could call myQuery.iterator() or myStruct.iterator() and have the same functionality? Or even better, why not have those collections all extend an iterator class so that it could be simplified even futher with myQuery.hasNext() or myStruct.hasNext().
Keep in mind, this discussion is only coming from the perspective of the programming interface itself, and I am not going to get into the differences behind the scenes of how a query result is actually a set of arrays of columns, or how an array differs from a struct. My point is simply that if we have these abstractions, it sure would be cool if they were consistent, but we were still able to call specific functions on them like ArrayFind() , StructDelete(), etc. If we had this ability, our loops in CFSCRIPT would be a lot more consistent as well.
With that said…. I will leave you with my wishful implementation for writing loops in CFML:
<cfloop condition="#myQuery.hasNext()#"> <cfset thisRow = myQuery.next() /> <cfset doStuff() /> </cfloop> <cfloop condition="#myArray.hasNext()#"> <cfset thisItem = myArray.next() /> <cfset doStuff() /> </cfloop> <cfloop condition="#myStruct.hasNext()#"> <cfset thisItem = myStruct.next() /> <cfset doStuff() /> </cfloop>