The Elvis Operator Can Be Chained Multiple Times In A Single Expression In Lucee CFML 5.3.3.62
In Lucee CFML, the "Elvis operator" - ?:
- is a binary operator that returns the first operand if it is non-null; otherwise, it evaluates and returns the second operand. I haven't used the Elvis operator all that much, so I am still getting used to how it works. And, historically, I've only ever used it once in a single expression. The other day, however, I had a scenario where I wanted to use it several times in a single expression; and, I was happy to find that it works exactly as you might hope in Lucee CFML 5.3.3.62.
To see what I mean, take a look at this trite example:
<cfscript>
// The Elvis operator can be chained several times in a single expression.
result = ( nullValue() )
?: nullValue()
?: nullValue()
?: nullValue()
?: "fall-back value"
;
echo( "Result: #result#" );
</cfscript>
Obviously, this expression makes no sense; but, it demonstrates that the ?:
operator can be chained together multiple times within a single expression. And, when we run the above ColdFusion code, we get the following output:
Result: fall-back value
As you can see, the ?:
operator kept evaluating its second operand until it hit one - "fall-back value" - that was non-null.
The reason this came up for me was that I had an API response object that reported error messages in a variety of ways. And, instead of being graceful in the way that I was inspecting the response, I just wanted to heavy-hand the approach with the Elvis operator in conjunction with the Safe-Navigation operator to find the relevant error codes:
<cfscript>
apiResponse = {
errors: {
transaction: {
key: "info.number"
}
}
};
// I had an API response object that could report several different types of errors
// and I didn't want to build a lot of logic about picking the response apart. So,
// I used the safe-navigation operator in conjunction with the Elvis operator to
// try and locate the known structures.
error = ( apiResponse?.errors?.validation?.token )
?: apiResponse?.errors?.validation?.field
?: apiResponse?.errors?.transaction?.key
?: "unknown"
;
echo( "Error: #error#" );
</cfscript>
Here, I'm using the Safe-Navigation operator to just blindly reach into the API response, understanding that the Safe-Navigation operator will return null if it can't find the desired object-query. Then, I use the Elvis Operator to continually "fall back" to other potential error locations. And, ultimately, I just use a back-up value if I can't locate the error.
And, when we run the above ColdFusion code, we get the following output:
Error: info.number
In retrospect, I had no reason to believe that the Elvis operator couldn't be chained multiple times in a single expression. After all, other binary operators like ||
and &&
can be chained like this. However, sometimes things just don't connect in my mind until I see them on paper. And, now I can clearly see that the Elvis operator can be chained multiple times within a single expression in Lucee CFML 5.3.3.62. This works particularly well in conjunction with the Safe-Navigation operator.
Want to use code from this post? Check out the license.
Reader Comments
Ben. What does this operator do:
Is it replicating this:
@Charles,
That's exactly right.
?.
is the Safe-Navigation operator, which will traverse the given path/property and returnnull
if the given value does not exist. You can think of it like this --a?.b
-- is akin to:... where it will try to access property
b
on objecta
; and, it is it not here, it will returnnull
.Ben. Is the Safe-Navigation operator a Lucee only thing or does it work in ACF? I have never seen it used before.
It looks amazing. It's going to save me so much coding. No more excessive use of StructKeyExists(), although, theoretically I could use IsDefined(), but for some reason, I don't like using the latter. Someone told me that it's slower than StructKeyExists()? But, I guess we are talking milliseconds and in any case:
Is probably slower to parse than:
But I love the efficiency of:
I am really looking forward to using this and I am using CF2018, as well, so I should be good to go?
@Charles,
I believe that it is in Adobe ColdFusion as well. But, I'm not 100% sure on that. It also exists in TypeScript.
I just had a play this morning and I can confirm that the Safe Navigation operator works in ACF 2018! Awesome...
@Ben,
Sorry, I think I have to amend that last comment. I am not sure that it exists in TypeScript -- but it can be used in parts of Angular (in its templates). But, I think that is Angular-specific.
Yes. I often see you use it, in your Angular tutorials, so I guess it must work?
I know it doesn't exist in JS, so I would be interested to see what Angular converts it to, behind the scenes, at build time...