On Null

I'm finally doing a lot of work with CF 9's ORM and I'm finding that dealing with null values in CFML can be quite a pain, especially when working with relationships. One thing that comes up quite a bit is iterating over child collections. ColdFusion goes out of it's way to shield developers from null values, yet when an entity has an empty collection ColdFusion returns a null. (Long time user of CFML would likely expect an empty array here, similar to how <cfquery> returns and empty string for null values, but this is not the case.) This means I end up doing something like this quite a bit:

<cfloop array="#IsNull(parent.getChildren())?[]:parent.getChildern()#" index="c">
...
</cfloop>

A few things could be done to improve on this. One option would be to return empty arrays for null collections, but given that CF 9 currently returns null, I don't think this is a realistic option. The cat is already out of the bag, so to speak.*

Another option would be to support null values in Boolean expressions and introduce something like Groovy's Elvis operator. Then this code could be shortened to:

<cfloop array="#parent.getChildren()?:[]#" index="c">
...
</cfloop>

It may not seem like much, but I think this would be a huge improvement.

Another problem with ORM and nulls and is nested entities. As it stands now, attempting to access deeply nested entities will throw an error if any item in the tree is null. Take the following code:

// throws an error if parent has no child
gc = parent.getChild().getGrandChild();

If the parent object has no children then this will throw an error. Again, it would have been nice if this just returned a blank string, but that isn't the case. What could be done would be the introduction of something like Groovy's safe navigation operator into CFML. Combined with the Elvis operation, the above code could be shortened to the following while still handling nulls:

gc = parent?.getChild()?.getGrandChild()?:"";

Again, a very small change that could go a long way in making CFML easier to use.

* In the parent.getChildren() example above, what is actually returned is an empty PersistentBag. ColdFusion interprets this a null, so while this would throw an error:

// this throws an error
if (parent.getChildren()) {
WriteOutput("No Children");
}

the following two examples should work:

// this works
if (IsNull(parent.getChildren())) {
WriteOutput("No Children");
}
// this works if (parent.getChildren().isEmpty()) {
WriteOutput("No Children");
}

Comments
Dan G. Switzer, II's Gravatar In JavaScript, you could do:

parent.getChildren() || []

Instead of:
IsNull(parent.getChildren())?[]:parent.getChildern()

I wonder if that works in CF9?
# Posted By Dan G. Switzer, II | 2/26/11 3:35 PM
BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.