Skip to main content
Ben Nadel at Scotch On The Rock (SOTR) 2010 (London) with: John Whish and Kev McCabe
Ben Nadel at Scotch On The Rock (SOTR) 2010 (London) with: John Whish Kev McCabe

ColdFusion 10 - Looping Over Function Arguments

By
Published in Comments (6)

Since ColdFusion 9.0.1, CFScript has supported using a FOR-IN loop construct for both arrays and structures. In arrays, it loops over the indices; in structures, it loops over the keys. Typically, this is a clear-cut piece of functionality. But, when it comes to the Arguments collection, which exhibits both Array and Struct behavior, the FOR-IN loop can be a bit confusing. This duality tripped me up the other day. While ColdFusion offers an existing way around this (ie. using a standard FOR-LOOP), I thought it would be nice to briefly explore Arguments-looping in ColdFusion 10.

NOTE: At the time of this writing, ColdFusion 10 was in public beta.

While the Arguments collection exhibits both Array-like and Struct-like behavior, if you try to iterate over it using a FOR-IN loop, you'll quickly discover that it uses struct-iteration, not array-iteration. To force array-iteration, you could fallback to using an explicit FOR-LOOP; or, you could use one of ColdFusion 10's new "functional programming" methods for enhanced clarity.

In the following demo code, I'm simply going to demonstrate the various types of Arguments-iteration that we now have available in ColdFusion 10:

<cfscript>


	// I simply provide a harness for exploring the relationship
	// between the Arguments scope and script-based iteration.
	function doSomething( argA, argB ){

		// First, try the FOR-IN loop (ColdFusion 9.0.1).
		writeOutput( "FOR-IN Loop <br />" );

		for (var i in arguments){

			writeOutput( "[#i#]: " );
			writeOutput( arguments[ i ] & "<br />" );

		}


		// Now, try the structEach() loop (ColdFusion 10).
		writeOutput( "<br />" );
		writeOutput( "structEach() Loop <br />" );

		structEach(
			arguments,
			function( key, value ){

				writeOutput( "[#key#]: " );
				writeOutput( value & "<br />" );

			}
		);


		// Now, try the arrayEach() loop (ColdFusion 10).
		writeOutput( "<br />" );
		writeOutput( "arrayEach() Loop <br />" );

		arrayEach(
			arguments,
			function( value ){

				writeOutput( value & "<br />" );

			}
		);


		// Now, try the FOR-I loop.
		writeOutput( "<br />" );
		writeOutput( "FOR-i Loop <br />" );

		for (var i = 1 ; i <= arrayLen( arguments ) ; i++){

			writeOutput( "[#i#]: " );
			writeOutput( arguments[ i ] & "<br />" );

		}

	}


	// ------------------------------------------------------ //
	// ------------------------------------------------------ //


	// Try the script - notice that there are MORE parameters in this
	// invocation than there are arguments defined in the function
	// signature.
	doSomething( "Our", "Deepest", "Fear" );


</cfscript>

As you can see, we're using the following approaches:

  • FOR-IN
  • structEach() - New in ColdFusion 10
  • arrayEach() - New in ColdFusion 10
  • FOR-I

When we run the above code, we get the following output:

FOR-IN Loop
[3]: Fear
[ARGB]: Deepest
[ARGA]: Our

structEach() Loop
[ARGA]: Our
[3]: Fear
[ARGB]: Deepest

arrayEach() Loop
Our
Deepest
Fear

FOR-i Loop
[1]: Our
[2]: Deepest
[3]: Fear

This is a really minor post, I know; but, the dual-nature of the Arguments scope planted a little bug in an application I was writing the other day, so I thought it was worth sharing.

Want to use code from this post? Check out the license.

Reader Comments

4 Comments

This might be a bit off topic, but while I like the functionality of arrayEach and structEach, I would have preferred a more conventional syntax. For example:

If x is a struct:

x.each(function(key,value){
//Do stuff
});

If x is an array:

x.each(function(value){
//Do stuff
});

15,919 Comments

@Scott,

I think that sentiment is one commonly held in the ColdFusion world. I have been in meetings with Adobe where that is discussed and I think the feeling is that it would just be too big a departure for the current syntax and would basically kill backwards compatibility. But, I agree, that would be awesome.

198 Comments

@Ben:

I labored hard when they introduced the Image* functions that they be implemented as objects and not dozens of function calls.

They just keep polluting the function name space and I think that also tends to promote procedural code in some way. I've also wondered if they start using a more OO approach, if maybe people the CF haters would somehow see it as a more legitimate language.

And I've never understood the "backwards compatible" argument about the approach. If you're adding new functionality, then by it's nature it's not backwards compatible. (Granted, you could add functions that emulate compatibility, but that's a different issue.)

15,919 Comments

@Jim,

Yeah, the For-In construct is awesome! I've been on ColdFusion 8 for so long, I forgot that it had been added in ColdFusion 9. That's the problem with not upgrading - you forget about the cool new features :(

@Dan,

I agree - if ColdFusion took on a more object-oriented approach, I think it would get a better reputation. Plus, I think it would be possible to build "wrapper" functions that just invoke the object methods in turn in order to create backwards compatibility. But, as you say, when you add new functionality, it seems that backwards compatibility becomes a moot point.

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel