Monday, 15 June 2015

CFML expectation management: when are empty elements respected?

G'day:
Couldn't fit this into 140 chars, so it's not gonna be a Twitter message, but instead a short article here. It turns out I don't quite get "lists" in CFML. Or... I'm just being daft. You decide. And tell me.

I've got this code:

// emptyElements.cfm

l="e";
c="";
l = listappend(l,c);
l = listappend(l,"");
l = listappend(l,"");
writeOutput("[#l#]<br>");

l="";
c="e";
l = listappend(l,c);
l = listappend(l,"");
l = listappend(l,"");
writeOutput("[#l#]<br>");

l="";
c="";
l = listappend(l,c);
l = listappend(l,"");
l = listappend(l,"");
writeOutput("[#l#]<br>");

Here I build three lists:
  • one starts with an element, then I append three empty elements to it;
  • one starts empty, then I append a populated element, followed by two empty elements;
  • the last starts empty, and I append three empty elements to it.

A quick quiz... assuming you understand that - by default - CFML lists do not respect empty elements, what would you expect the output to be here?

I'd expect this:

[e]
[e]
[]


Appending an empty element to a list should not append a delimiter as well, as it's unnecessary: empty elements are ignored by lists.

What I do get is this:

[e,,,]
[e,,]
[]


This makes no sense to me: CF (and, I hasten to add, Railo and Lucee) aren't following their own rules here, are they? If empty elements are actually appended (although they shouldn't be), then the results should be:

[e,,,]
[,e,,]
[,,,]


I start with a value and append three blanks
Or I start with nothing, append an actual element, then two blanks
Or I start with nothing and append three blanks.

Whichever way one spins it, I should have the original and three appended elements.

In reality, I should just have the populated element (either the initial value, or the element), and nothing else.

The ColdFusion docs for listAppend() contradict themselves here. On one hand they say this:

If value = "", returns a copy of the list, unchanged.

But they then go on to demonstrate this:
Statement:
ListAppend('elem1,elem2', '' )

Output:
elem1,elem2,

Comment:
Appended element is empty; delimiter is last character in list; list length is 2.

(also note two things: it's an expression, not a statement; and it doesn't output anything, that's just the value of the expression. But anyway).

Lucee's doc's for listAppend() are - as is generally the case - neither use nor ornament. They just describe the function signature, and offer no further insight. Not helpful.

But this seems such a fundamental f***-up, I'm certain I'm missing something obvious.

What is it??

--
Adam