Skip to main content
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: Jacob Holloway
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: Jacob Holloway ( @jakeishTweets )

Iterating Over Function Arguments Using CFLoop In Lucee CFML

By on
Tags:

In my previous post on flattening arrays in ColdFusion, I mentioned that the arguments scope in a Function body acts as both an Array and a Struct. This is a truly great feature of ColdFusion; but, iterating over such a dynamic data structure can be confusing at times. Luckily, ColdFusion also gives us the highly dynamic CFLoop tag. We can use CFLoop to iterate over the arguments scope using either Array iteration or Struct iteration.

To see this in action, I've create a function with two named arguments; but, I'm going to pass-in four arguments. Then, I'm going to iterate over the arguments scope twice: once as a Struct and once as an Array:

<cfscript>

	testArgIteration( "aye", "bee", "see", "dee" );

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

	/**
	* I test Function argument iteration using the CFLoop tag.
	* 
	* NOTE: I have TWO NAMED ARGUMENTS defined, but I'm passing-in FOUR arguments.
	*/
	public void function testArgIteration( a, b ) {

		// Using CFLoop to iterate over the arguments scope as a Struct. In this case, the
		// "key" is either the NAME of the argument, if it exists; or, the INDEX of the
		// argument if it is unnamed.
		loop
			key = "local.key"
			value = "local.value"
			struct = arguments
			{

			dump({
				key: key,
				value: value
			});

		}

		// Using CFLoop to iterate over the arguments scope as an Array. In this case, the
		// "key" is ALWAYS the INDEX of the argument, regardless of whether or not the
		// arguments are named.
		// --
		// NOTE: We could have use the attributes "key" and "value" here as well, and it
		// would have worked the same. I am opting for "index" and "item" since they feel
		// more Array-appropriate.
		loop
			index = "local.index"
			item = "local.item"
			array = arguments
			{

			dump({
				index: index,
				item: item
			});

		}

	}

</cfscript>

Notice that when I am providing the arguments scope to the CFLoop struct attribute, I'm using the key and value attributes for iteration. And, when I provide the arguments scope to the CFLoop array attribute, I'm using the index and item attributes for iteration. This difference in attribute selection isn't strictly necessary; however, I think it makes the code more clear.

Now, when we run this ColdFusion code, we get the following output:

All arguments output to screen during Struct and Array iteration using CFLoop in ColdFusion.

As you can see, we were able to iterate over the arguments scope as both a Struct and as an Array! Note that when treating the scope as a Struct, if we run out of "named arguments", the "index" variable will be the numeric offset of the argument.

The ColdFusion Function is a very dynamic, powerful construct in the CFML world. In fact, I listed "Named And Ordered Arguments" as one of the many reasons to fall back in love with modern ColdFusion. The arguments scope is certainly part of that power. And, the more we understand how to use the arguments scope, the better we can be at leveraging this great power.

Epilogue on structEach() and arrayEach()

It's also possible to iterate over the arguments scope using structEach() and arrayEach(). Frankly, I forgot these functions even existed since I moved to using member methods as often as possible. That said, at least in Lucee CFML, when I use arrayEach(), the "index" provided to the callback is the argument name, not its index.

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

Reader Comments

4 Comments

What I truly wish would get added to CFML? Function overloading. That would be awesome. Right now, you can at least use the "default" attribute on an argument, and use cfparam, as well.

But true detection of argument types and having CFML call the appropriately flavored function would be great. But the pre-compiler would also have to recognize duplicate function signatures.

Even better would be to maintain the fuzziness of argument types, and perhaps specifically indicate a given function should be inspected for overloading.

15,377 Comments

@Will,

I go back and forth on this idea of differentiating function signatures. I think there are definitely times when it would be great. But, then, I'll go and look through the Lucee CFML code (written in Java) and there's like 8 different versions of the call() method all with different types of arguments, and it feels a bit overwhelming to wrap my head around what is available.

That said, it would probably be kind of crazy to have 8 entirely differently named functions for the various combinations of arguments as well 🤣

All to say, I'm definitely curious to see what that would be like. But, it could also be a foot-gun as well.

Post A Comment — I'd Love To Hear From You!

Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
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.
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