Skip to main content
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: Jonathon Wilson
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: Jonathon Wilson ( @chilkari )

Adobe ColdFusion Elvis Operator Struggles With Nested Array References

By on
Tags:

In Lucee CFML, the Elvis Operator (null coalescing operator) is quite powerful. In fact, it can often replace the Safe Navigation operator when access values on deeply-nested structures. In contrast, the Elvis Operator in Adobe ColdFusion is much more problematic. And, in fact, I just ran into another rough edge in the ACF implementation. It seems that the Elvis operator has trouble with nested array references.

Nested Struct references seem to be fine in both Lucee CFML and Adobe ColdFusion. Both engines will happily return the empty-string for this nonsense expression:

( foo.bar.baz.kablamo ?: "" )

However, if we were to replace one of those intermediary undefined keys with an undefined array index, Adobe ColdFusion would break. Let's take a closer look and how it breaks at the various object paths.

In my Dig Deep Fitness app, when you perform a workout, I overlay the previous sets on top of the current sets. Of course, if this is the first time you've performed an exercise, there's no prior data to overlay. As such, I end up with an empty array; which I was attempting to safely consume with the Elvis operator.

The code looked something like this (heavily boiled down):

<cfscript>

	recentWorkouts = [
		{
			sets: [
				{ weight: 100, reps: 12 }
			]
		}
	];

	writeDump( recentWorkouts[ 1 ].sets[ 1 ].weight ?: "" );

</cfscript>

Here, I'm trying to access the first weight of the first sets of the first recentWorkouts. Notice that both recentWorkouts and sets is an array.

If we run the above "happy path" code (where everything is defined) in both Adobe ColdFusion and Lucee CFML, we get the following:

  • Lucee: 100
  • ACF: 100

Now, let's try commenting-out the contents of the sets:

<cfscript>

	recentWorkouts = [
		{
			sets: [
				// { weight: 100, reps: 12 }
			]
		}
	];

	writeDump( recentWorkouts[ 1 ].sets[ 1 ].weight ?: "" );

</cfscript>

If we run this code in both engines, we get:

  • Lucee: [empty string]
  • ACF: [empty string]

So far, both engines are successfully handling the undefined sets index. Now, let's try commenting-out the sets entirely:

<cfscript>

	recentWorkouts = [
		{
			// sets: [
			// 	// { weight: 100, reps: 12 }
			// ]
		}
	];

	writeDump( recentWorkouts[ 1 ].sets[ 1 ].weight ?: "" );

</cfscript>

If we run this code in both engines, we get:

  • Lucee: [empty string]
  • ACF: Element SETS is undefined in a CFML structure referenced as part of an expression.

Now let's try commenting-out the first workout:

<cfscript>

	recentWorkouts = [
		// {
		// 	// sets: [
		// 	// 	// { weight: 100, reps: 12 }
		// 	// ]
		// }
	];

	writeDump( recentWorkouts[ 1 ].sets[ 1 ].weight ?: "" );

</cfscript>

If we run this code in both engines, we get:

  • Lucee: [empty string]
  • ACF: The system has attempted to use an undefined value, which usually indicates a programming error, either in your code or some system code. Null Pointers are another name for undefined values.

As you can see, Lucee CFML continues to operate properly as we comment-out items farther up the chain of nested values. Adobe ColdFusion, on the other hand, starts to throw different errors depending on the level of nesting.

ASIDE: Not catching this in the code was my bad - I was sloppy in testing my code after making changes.

I'm so used to using the Elvis / Null Coalescing operator in Lucee CFML because it is so robust and powerful. I have to remember that it has many more rough-edges and gotchas in Adobe ColdFusion. Especially, as it were, with array references.

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

Reader Comments

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

Post a Comment

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