Skip to main content
Ben Nadel at dev.Objective() 2015 (Bloomington, MN) with: Kitt Hodsden
Ben Nadel at dev.Objective() 2015 (Bloomington, MN) with: Kitt Hodsden

Struct Iteration With CFLoop Includes Super Intuitive Aliases In Lucee CFML 5.3.6.61

By
Published in Comments (2)

A few months ago, I was excited to discover that CFLoop exposes both keys and values during Struct iteration in Lucee CFML. In that post, I demonstrated that the "key" could be accessed via index and the "value" could be accessed via item. Well, life just keeps getting better! Earlier this week, I discovered (in the Lucee documentation) that the CFLoop tag has even more intuitive aliases for Struct iteration! I'm not sure how I missed this before; but, apparently you can now use key, value, and struct in Lucee CFML 5.3.6.61.

To see this in action, I've defined a Struct and am going to loop over it using three different methods:

  1. The old-school item approach.
  2. The newer index and item approach.
  3. The awesome key, value, and struct approach.

Not that I am using the Elvis operator to manage null value references in the following code:

<cfscript>

	data = [
		id: 1,
		name: "Yoga Socks",
		sku: "t-12345-yogasocks",
		price: 14.95,
		weight: 194,
		createdAt: now(),
		deletedAt: nullValue()
	];

	// Traditional Struct iteration in ColdFusion only exposed the "item", which was the
	// key being accessed. It was then up to the iteration body to access the "value"
	// using the iteration key.
	loop
		item = "key"
		collection = data
		{

		value = ( data[ key ] ?: "undefined" );

		echo( "#key# : #value# <br />" );

	}

	echo( "<hr />" );

	// Then, Lucee CFML added the ability to define both the "index" and the "item"
	// during Struct iteration wherein the "index" was the "key" and the "item" was the
	// key-value.
	loop
		index = "key"
		item = "value"
		collection = data
		{

		echo( "#key# : #( value ?: 'undefined' )# <br />" );

	}

	echo( "<hr />" );
	
	// BUT, I just discovered (from reading the documentation) that Lucee CFML actually
	// has really helpful aliases for Struct iteration components, making them much
	// easier to write and read:
	// --
	// * Struct instead of Collection.
	// * Key instead of Index.
	// * Value instead of Item.
	loop
		key = "key"
		value = "value"
		struct = data
		{

		echo( "#key# : #( value ?: 'undefined' )# <br />" );

	}

</cfscript>

As you can see, the last CFLoop tag uses key, value, and struct for Struct iteration. Super intuitive! And, when we run the above ColdFusion code, we get the following output:

Struct iteration performed three different ways in Lucee CFML.

How cool is that! It feels like with every passing day, I find yet another reason to love Lucee CFML! This language just keeps getting more and more world-class.

Epilogue on .each()

Lucee CFML is so freaking flexible. And, because I am sure there are people who will look at me "using tags in script" and begrudge it, it's worth mentioning that you can always use the .each() iteration method to expose all the same data-points:

<cfscript>

	data = [
		id: 1,
		name: "Yoga Socks",
		sku: "t-12345-yogasocks",
		price: 14.95,
		weight: 194,
		createdAt: now(),
		deletedAt: nullValue()
	];

	data.each(
		( key, value, collection ) => {

			echo( "#key# : #( value ?: 'undefined' )# <br />" );

		}
	);

</cfscript>

I use both approaches, depending on the situation. One nice thing about using the CFLoop tag directly in CFScript is that - according to Gert Franz - using the tag is actually faster than the Function-based iteration. A micro-optimization to be sure; but, it's good to have in the back of your mind.

Of course, another benefit of using Function-based iteration is that you have the option to leverage parallel iteration using asynchronous threads in Lucee CFML, which is all flavors of awesome for high-latency actions.

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

Reader Comments

9 Comments

Ben, your last example also shows the beauty and simplicity of arrow functions , which suits perfectly for these iterations. For such a long time it hurt me trying to understand arrow functions, but these cases shows exactly why they've been made. Thanks for the blog post.

15,902 Comments

@Andreas,

Totally agreed. I've been using the .map() and .filter() functions a lot more lately in my programming. It's been really enjoyable; and I think is easy enough to follow / has good readability.

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