Skip to main content
Ben Nadel at cf.Objective() 2014 (Bloomington, MN) with: Dan Wilson
Ben Nadel at cf.Objective() 2014 (Bloomington, MN) with: Dan Wilson

The Elvis / Null Coalescing Operator Can Sometimes Replace The Safe Navigation Operator In Lucee CFML 5.3.6.61

By
Published in Comments (7)

Yesterday, when I was listening to the latest episode of the Modernize or Die Podcast, Brad Wood said something that I had not heard before: that the Safe Navigation operator can usually be replaced with the Elvis / Null Coalescing operator in Lucee CFML. I had always just assumed that without the safe navigation syntax, undefined keys would still throw null-reference errors, regardless of whether or not the Elvis operator was involved. As it turns out, Brad was right! Though, it only works if the given expression does not contain a method call. Since this was news to me, I thought it was worth a quick demo in Lucee CFML 5.3.6.61.

As a quick recap, the Safe Navigation operator allows you to safely traverse an object graph without throwing null-reference errors by using ?. instead of . when drilling down through object keys:

foo?.bar?.baz

If any of the keys along the way do not exist, the overall expression returns null instead of throwing an error.

The Elvis / Null Coalescing operator (?:), on the other hand, allows you to provide a fallback value for an expression that returns a null value:

foo?.bar?.baz ?: "fallback value"

Now, what Brad is saying is that in this previous expression, I can actually remove the Safe Navigation operator and just use the Elvis operator. To demonstrate, here's a tiny ColdFusion script:

<cfscript>

	echo( "Foo exists: " & variables.keyExists( "foo" ) );
	echo( ". " );

	echo( foo.bar.baz ?: "Null value fallback" );

</cfscript>

In this small demo, foo doesn't exist. And, it's where I would normally use the Safe Navigation operator. However, since we are also including the Elvis operator, the previous ColdFusion script results in the following output:

Foo exists: false. Null value fallback

As you can see, even though foo doesn't exist, we can still side-step null reference errors by using the Elvis operator to provide a fallback value.

This is pretty cool! But, be aware that it appears to breakdown if the left-hand expression contains a method call. For example, if we call this ColdFusion code:

<cfscript>

	echo( "Foo exists: " & variables.keyExists( "foo" ) );
	echo( ". " );

	echo( foo.bar.baz() ?: "Null value fallback" );

</cfscript>

... which is the same as above, except that our last object reference is .baz(), not .baz, we get the following ColdFusion error:

variable [foo] doesn't exist

It doesn't matter that the Method invocation operator (()) is on the last object reference - it could be anywhere in the left-hand expression and the outcome is the same.

This is true even if the method being invoked exists:

<cfscript>

	echo( foo().bar.baz ?: "Null value fallback" );

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

	public void function foo() {
		// No-op.
	}

</cfscript>

In this case, the foo() function exists, but returns null. And, when we run this code, we get the following ColdFusion error:

No matching property [bar] found

It's really cool that the Elvis operator can stand-in, so to speak, for the Safe Navigation / Null Coalescing operator in simple expressions - thanks Brad! However, just be aware that this does break down in more complex expressions. Of course, you can always use the Safe Navigation operation in conjunction with the Elvis operator in those cases.

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

Reader Comments

226 Comments

I've forever wished I could use JS syntax for this...

foo.bar.baz || "Null value fallback"

I hadn't considered using the elvis operator to mimic this behavior. Cleaver. Unfortunately, it does not work in Adobe CF. Another (useful) example of where Lucee shines.

15,811 Comments

@Zac,

Ha ha :D Not this time.

@Chris,

Yeah, Lucee CFML is pretty grand. That said, the safe-navigation operator is in TypeScript if you ever go that route for your JavaScript.

84 Comments

Brad's recommendation is fine ("skip Safe Navigation operator & just use the Elvis operator") if you develop only for Lucee and have no expectation of your code being cross-compatible with Adobe.

foo?.bar?.baz ?: "fallback value" works with CF2016-2021 as well as Lucee, but you can't skip directly to solely using the Elvis operator with ColdFusion. 😞

NOTE: I returned this article while refreshing myself on the syntax and to further test. The info regarding the safe navigation operator should be added to CFDocs. (I've started using the Elvis operator and it really reduces logic while still being readable. Thx!)

15,811 Comments

@James,

It's funny you bring this up. I've been heavily updating my blogging platform lately, which runs on Adobe ColdFusion 2021 (currently); and, I think I was bit by this very thing! I tried to jump right to the ?: and I got some null-reference errors.

.... unless I'm thinking about JavaScript / ES2021 🤔 I know I was trying to do this somewhere just recently and had to go back and add all the safe-navigation operators.

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