Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: Jonathan Hau and David Bainbridge and Scott Markovits
Ben Nadel at InVision In Real Life (IRL) 2019 (Phoenix, AZ) with: Jonathan Hau , David Bainbridge ( @redwhitepine ) , and Scott Markovits@ScottMarkovits )

Struct Iteration Methods Like Each, Map, And Filter Include Null Values In Lucee CFML 5.3.3.62

By Ben Nadel on
Tags: ColdFusion

Earlier this week, I was working on some reflection-style code in CFML wherein I was recursively looking through structs of data. As I was doing this, it occurred to me that some of the values stored in the structs could be null; and, I wasn't sure off-hand how Lucee would handle these values during iteration. I've already demonstrated that array iteration with null values can be surprising; so, I wanted to take a moment and look at how null values are handled in struct iteration methods (ex, .each, .map, .filter, .every, .reduce) in Lucee CFML 5.3.3.62.

To test this, I created a ColdFusion struct in which one of the values is defined using the nullValue() function. Then, I attempt to iterate over the key-space and examine each iteration value:

<cfscript>

	data = [
		a: 1,
		b: nullValue(),
		c: 3
	];

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

			echo( key & " : " );
			// Using the Elvis operator (null coalescing operator) to check whether or
			// not the current iteration value is null.
			echo( value ?: "[null]" );
			echo( "<br />" );

		}
	);

</cfscript>

When we run this ColdFusion code, we get the following output:

A : 1
B : [null]
C : 3

As you can see, the key with the nullValue() value is included in the struct iteration. This code demonstrates the behavior of .each(); however, the same behavior is exhibited in .map(), .filter(), and .reduce().

This behavior isn't entirely surprising. I've written about the handling of null arguments over a decade ago. But, I'm still trying to get a sense of how the CFML language has evolved since I've switched from ColdFusion 10 to Lucee CFML. As such, little sanity checks like this are helpful as I continue to build my mental model.



Reader Comments

Interestingly:


<cfscript>

function test() {
}

data = [
		a: 1,
		b: test() ?: nullValue(),
		c: 3
	];

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

			echo( key & " : " );
			// Using the Elvis operator (null coalescing operator) to check whether or
			// not the current iteration value is null.
			echo( value ?: "[null]" );
			echo( "<br />" );

		}
	);

</cfscript>

Throws an error, even though the function test() should return null. But the following, does not throw an error:


<cfscript>

function test() {
}

t=test();

data = [
		a: isNull(t),
		b: 2,
		c: 3
	];

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

			echo( key & " : " );
			// Using the Elvis operator (null coalescing operator) to check whether or
			// not the current iteration value is null.
			echo( value ?: "[null]" );
			echo( "<br />" );

		}
	);

</cfscript>

Reply to this Comment

Apparently, if we enable null support by using lucee server admin --> Language/compiler and setting Null support to complete support, then the first example will not throw an error.

The question is, is it better to use partial null support or complete null support. This is a Lucee only conundrum.

ACF2018 seems to have complete null support.

Reply to this Comment

Sorry.

ACF2018 seems to have partial null support.

Try this test instead:

<cfscript>
	function test() {
	}
	WriteDump(test());
	t=test();
	WriteDump(t);
	WriteDump(isNull(t));
	WriteDump(isNull(notexisting));
</cfscript>

Using both Lucee 5 partial & complete null support & ACF2018!

Reply to this Comment

My first example should have been:


<cfscript>

function test() {
}

t=test();

data = [
		a: 1,
		b: t,
		c: 3
	];

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

			echo( key & " : " );
			// Using the Elvis operator (null coalescing operator) to check whether or
			// not the current iteration value is null.
			echo( value ?: "[null]" );
			echo( "<br />" );

		}
	);

</cfscript>

This throws an error in Lucee, but the following does not throw an error in Lucee:


<cfscript>

function test() {
}

data = [
		a: 1,
		b: test(),
		c: 3
	];

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

			echo( key & " : " );
			// Using the Elvis operator (null coalescing operator) to check whether or
			// not the current iteration value is null.
			echo( value ?: "[null]" );
			echo( "<br />" );

		}
	);

</cfscript>

So, it seems to be something about assigning null to a variable that causes an issue. Apparently, applying complete null support resolved this issue.

Reply to this Comment

@Charles,

This has also tripped me up many times. Technically, there's nothing wrong with null values. What does cause a problem is attempting to reference a null value. I assume this works better when you enable "complete" null support because null becomes a first-class citizen at that point and you can reference a null value just like you would any other value.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
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.