CFML wishlist: All collections should extend Iterator

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>

Using Java instead of CFFILE and CFDIRECTORY

There are several reasons why jusing Java in place of CFFILE of CFDIRECTORY might be a good idea.  In many cases such as shared hosting environments, hosts block use of those tags.  While it obviously goes against the spirit of their intent of doing this, sometimes applications just need that functionality and this becomes a real roadblock for developers.

Secondly and in my opinion a very important reason is for performance.  Jusing Java to perform these tasks can be 10-20 times faster than using tag calls.  Fellow CF’er Phillip Holmes offers this reason: The reason why the Java example is much faster is because when you call the cffile tag, you’re actually calling a class that groups Java functionality together. This class is located in the lib/cfusion.jar file. By using the call to the Java.io namespace, you’re bypassing the excess functionality and error checking that CFMX does for you. So, you’re streamlining your operation by not instantiating code that you don’t use.

Reading a directory:
First let’s read a directory.  One thing that is worthy of mention is that this method will return an array rather than a ColdFusion query object, so this might not be just a plug-n-play change to code that has existing cfdirectory calls.  You will likely have to change the way you are accessing the returned data.  So, how do you do it?

<cfscript>
ourDirectory = expandPath(“./”);
directoryList = createObject(“java”,”java.io.File”).init(ourDirectory).list();
</cfscript>

This is obviously a bit more code to have to type out, so you may want to keep a UDF available that returns your array when a directory is passed to it.

Writing a file:
Trevor Burnette has given a great example of how to write files with using Java instead of CFFILE. I have tried this and found tremendous performance gains using his method. Go check out his blog for some good info.

Model Glue…. for Java!

I picked this up off of the Model Glue list.  Chris Scott has made a Java implementaion of Model Glue.  One of his reasons was to perhaps make Java development more reachable for ColdFusion developers who have had trouble getting their heads around the environment in general.  His thinking is that if you have worked with an MVC framework before that ideally looking at a a familiar framework in Java might help the transition.

This means that Model Glue is now available for 3 languages! (there is a .NET port as well).  This is great validation for Joe Rinehart’s hard work on the framework.