ColdFusion 10 - Looping Over Function Arguments

Posted April 16, 2012 at 9:57 AM by Ben Nadel

Tags: ColdFusion

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.


You Might Also Be Interested In:



Reader Comments

Apr 16, 2012 at 10:23 AM // reply »
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
});


Apr 16, 2012 at 10:27 AM // reply »
11,243 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.


Apr 16, 2012 at 3:20 PM // reply »
17 Comments

Huh, I didn't know there was a for-in structure in CF yet... *rubs hands evily*

time to revisit some code!


Apr 16, 2012 at 5:00 PM // reply »
171 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.)


Apr 17, 2012 at 10:46 AM // reply »
11,243 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.


Apr 17, 2012 at 11:30 AM // reply »
2 Comments

@ Ben
@Dan

In CF9 I believe they incorporated ORM (Object Relational Mapping). I haven't explored it yet but just thought to offer some input. :) Hope it helps. There is a video on it in the CF9 DevNet.

http://www.adobe.com/devnet/coldfusion/articles/cf9_cfbuilder_videos.html

(It's the first vid by Ben Forta; yes, another ubber Ben in the world of CF!)


Jul 21, 2012 at 1:16 AM // reply »
1 Comments

jhnkiylk6e7 67575


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 23, 2013 at 3:55 AM
Javascript Array Methods: Unshift(), Shift(), Push(), And Pop()
very interesting and helpful too. ... read »
May 22, 2013 at 5:35 PM
Script Tags, jQuery, And Html(), Text() And Contents()
This is still an issue 2 years later. jQuery is supposed to remediate these cross browser issues, no? I have been unable to find any statement from the jQuery team calling this behavior "by de ... read »
May 22, 2013 at 12:44 PM
Ask Ben: Query Loop Inside CFScript Tags
In cf10, if you call a function that has: local.result = {}; local.result.msg = ""; local.svc = new query(); local.svc.setSQL("SELECT * FROM..."); local.obj = local.svc.exe ... read »
May 22, 2013 at 12:29 PM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Ben: What version of Java are you using? Also, did you test users.id to see what Java reports as the data type? I wonder if it's not a Java primitive data type, but getting returned as something ... read »
May 22, 2013 at 11:47 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Dana, Awesome - so it looks like this bug was fixed in ColdFusion 10. Thanks so much for double-checking that. ... read »
May 22, 2013 at 11:37 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
When I c&p and run on cf10, I get: Selected User IDs: 1,4 User 1 selected: YES - YES User 2 selected: NO - NO User 3 selected: NO - NO User 4 selected: YES - YES User 5 selected: NO - ... read »
May 22, 2013 at 11:27 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
@Tom, Good thought, but no dice. Both of these still exhibit the same behavior: users.id[ users.currentRow ] users[ "id" ][ users.currentRow ] It's just something whacky happening with ... read »
May 22, 2013 at 11:07 AM
Strange Interaction Between DeserializeJson(), ArrayContains(), And Database Values In ColdFusion
Could your problem be that "users.id" is actually an ARRAY, not a single value? Perhaps try it again with "users.id[1]" (I only have CF8 here at work). ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools