ColdFusion 8-Enhancements You May Have Missed

June 2008

<cfscript> Enhancements

Poor <cfscript>! It can't be easy being the younger sibling to CFML tags. Natively, you can just do more with tags. Tags are arguably easier to learn and read, especially for beginners. Yet, since its introduction in ColdFusion 4.0, <cfscript> has dutifully done its job while getting none, or little, of the love.

Given that ColdFusion was marketed as an easy-to-learn tag-based language that could be adopted by non-programmers who were only familiar with HTML, why did Allaire make the effort to introduce <cfscript>? Perhaps it was an effort to add a sense of legitimacy for those who didn't view a tag-based language as a true language. Perhaps it was a matter of trying to appeal to more seasoned developers as well as beginners. In either case, <cfscript> wasn't without some serious limitations that prevented it from gaining widespread acceptance.

For example, while it boasted an ECMAScript-like syntax, which perhaps would have made it attractive to JavaScript developers, it was tied tightly enough to CFML that it used CFML operators. If you were used to writing the following to loop over an array in JavaScript:

for (var i=0; i<myArray.length; i++) {

… it wasn't quite a natural progression to write the same loop in cfscript:

for (i=1; i lt arrayLen(myArray); i=i+1) {

On the surface, it may look similar enough. But there are a few significant differences. First, the use of "lt" to represent the traditional "<" ('less than' operator). Second, the lack of a built-in increment operator. While ColdFusion does have a built-in incrementValue() function, that doesn't really do much to bridge the gap between <cfscript> and ECMAScript.

When you're used to using traditional comparison operators in a scripting language (<, =, >, etc), as well as using increment operators (++), you would likely end up losing more time than you'd save in <cfscript>. Why? Because chances are that you'd type out the loop using the traditional comparison operators, run your code, see the error, smack your forehead, modify the code, and repeat. Well, your forehead is going to love this. As of ColdFusion 8, cfscript supports all of the traditional comparison operators (<, <=, ==, !=, =>, >). In addition, both <cfscript> and CFML support the following operators as of ColdFusion 8:



ColdFusion Pre CF 8

ColdFusion 8











x = a mod b

x = a%b


Compound Addition

x = x + y

x += y


Compound Subtraction

x = x - y

x -= y


Compound Multiplication

x = x * y

x *= y


Compound Division

x = x / y

x /= y


Compound Modulus

x = x mod y

x %= y


Compound Concatenation


str = "abc";

str = str & "def";

str = "abc";

str &= "def";


Logical And

if (x eq 1) and (y eq 2)

if (x == 1) && (y == 2)


Logical Or

if (x eq 1) or (y eq 2)

if (x == 1) || (y == 2)


Logical Complement

if (x neq y)

if (! x == y)


For people who bounce back and forth between ColdFusion and languages like JavaScript or ActionScript, this should make the transitions significantly less jarring.

Array and Structure Enhancements

Arrays and structures are powerful constructs within the world of programming. While the naming conventions may be different, they exist in virtually every language. Creating even a moderately complex application without them would be an unpleasant experience to say the least. Hopefully you're already putting them to use. If you are, your life just got a little bit easier.

Creating Arrays

One of the perceived drawbacks to a tag-based language like CFML is that it can be a bit verbose. Consider the relatively straightforward task of creating an array and populating it with a small amount of data:

<cfset myArray  = arrayNew(1) />
<cfset myArray[1] = "Moe" />
<cfset myArray[2] = "Larry" />
<cfset myArray[3] = "Curly" />

In <cfscript> it gets a little bit better by cutting out some of the redundancy of the <cfset> tags:

myArray  = arrayNew(1);
myArray[1] = "Moe";
myArray[2] = "Larry";
myArray[3] = "Curly";

A little bit better. But if you're familiar with languages like JavaScript, ActionScript, Java, or others, you know that this can still be improved upon. That's exactly what Adobe's done with ColdFusion 8. ColdFusion 8 introduces shorthand notation for the creation of arrays.

<cfset myArray = [] />

The code above will create an empty array. In and of itself, this doesn't seem like a tremendous time saver. But, what if you could create the array and populate it at the same time?

<cfset myArray = ["Larry", "Moe", "Curly"] />

The square brackets tell ColdFusion that you're creating an array. Inside the square brackets, a comma-delimited list populates the array. One caveat to be aware of is that ColdFusion has never taken much of a liking to empty list elements. The following will throw an error:

<cfset myArray = ["Larry", , "Curly"] /> <!-- don't do this -->

If you're populating your array dynamically, take steps to ensure that there are no empty elements in the list.




Creating Structures

As with arrays, structures can now be created via a similar shorthand technique. One notable difference is that where arrays use square brackets, structures use curly braces:

<cfset myStruct = {} />

The other difference is that, while an array is simply a collection of values stored in a variable and accessible via index position, a structure is a collection of key value pairs. Consider the pre-ColdFusion 8 method of creating and populating a structure:

<cfset myStruct  = structNew() />
<cfset myStruct.firstName = "Charlie" />
<cfset myStruct.lastName = "Griefer" />
<cfset myStruct.location = "San Ramon, CA" />

Each value ('Charlie', 'Griefer', 'San Ramon, CA') has a corresponding key ('firstName', 'lastName', 'location'). In order to populate a structure using ColdFusion 8's new shorthand notation, you pass in a list of key value pairs.

<cfset myStruct = {firstName="Charlie", lastName="Griefer", location="San Ramon, CA"} />

Looping Over Arrays

ColdFusion 8 doesn't only make it easier to create arrays, but it also makes it easier to work with them. If you've ever worked with an array, chances are pretty good that you've also looped over an array. Here's how it used to be done:

<cfloop from="1" to="#arrayLen(myArray)#" index="idx">
#myArray[idx]#<br />

This is essentially a straightforward "for" loop. Assuming that 'myArray' has 10 elements in it, the loop will iterate from 1 to 10. The value of "idx" (the loop index) will increment with each iteration of the loop.

Within the loop, the element at the specified array position is manually accessed.

ColdFusion 8 introduces an array-based loop.

<cfloop array="#myArray#" index="arrayElement">
#arrayElement#<br />

It's no longer necessary to calculate the length of the array inside of the <cfloop> tag. Also very much worth noting is that the value of the index now corresponds to an array element itself. Whereas in the first example, the value corresponds to the iteration of the loop, it now represents the actual elements in the array. This is similar to the way that ColdFusion performs a list-based <cfloop>.

Looping Over Structures

Looping over a structure is still accomplished via a collection <cfloop>. This behavior has not changed with ColdFusion 8.

More Fun with Looping

In addition to the ability to easily loop over an array, ColdFusion 8 provides the ability to loop over a text file.

Prior to ColdFusion 8, this could be done, but it was a roundabout process.

<cffile action="read" file="c:myFilescontacts.txt" variable="myContacts" />
<cfloop list="#myContacts#" delimiters="#chr(13)&chr(10)#" index="line">

The first step involved a <cffile> to read the file into memory and store it in a variable. The next step was to loop over that variable as a list, using a carriage return/line feed as a delimiter.

ColdFusion 8 streamlines this process a bit by providing a file-based <cfloop> that behaves identically.

<cfloop file="c:myFilescontacts.txt" index="line">
#line#<br />

Provide a file based <cfloop> an absolute path to a text file, and it reads the file contents. This is similar to <cffile action="read" … /> but doesn't require an additional variable assignment. By default, ColdFusion will loop over each line in the file using carriage return/line feed as the delimiter.

The value of "index" can be any valid ColdFusion variable name. In this example, the value "line" appropriately demonstrates the expected behavior.

Additionally, you can also provide a characters attribute to a file-based <cfloop>. In doing so, you instruct the loop to iterate at every 'x' number of characters, rather than every line.

<cfloop file="c:myFilesbirthdays.txt" index="chars" characters="10">
#chars#<br />

In the example above, the value of chars for the first iteration of the loop will be the first 10 characters of the file. During the second iteration, the value will be characters 11-20, and so on.

Empty List Elements

As I had alluded to earlier, ColdFusion and empty list elements have had a problematic history, to say the least. Mailing lists and forums have seen their share of questions from people who were getting lists of data from external sources that would often include one or more empty list elements. Because ColdFusion ignored these empty elements, operations on these lists frequently yielded unexpected results.

Consider the following:

<cfset myList = "Larry,Moe,Curly,,Shemp" />

Notice the empty element between Curly and Shemp? Technically, this is a 5 element list. However, running a listToArray() function would result in a 4 element array.

<cfset myArray = listToArray(myList) />

Ideally the resulting array should have 5 elements, with an empty element at position 4. However, run the code above and you'll see that the output is 4.

With ColdFusion 8, listToArray() takes an optional 3rd argument, 'includeEmptyElements' (boolean). The default is "false", which provides the function with greater backward-compatibility. But by setting the value to "true", you'll get a 5 element array.

<cfset myArray = listToArray(myList, ',', true) />

Because both the 2nd and 3rd arguments are optional (the 2nd argument being the delimiter, which defaults to a comma), you'll need to include them both in order to use the includeEmptyElements argument.

Unfortunately, this enhancement didn't make it into other list functions, such as listLen(), and looping over a list-based <cfloop> with an empty element will still result in the empty element being skipped. However, the listToArray() enhancement gives you the ability to work around those limitations.


Undoubtedly, with each new release of ColdFusion, it's the new features rather than the enhancements that get the lion's share of the publicity. Understandably so, as Adobe continues the fine tradition of pushing the envelope that was started so many years ago by Allaire and then carried on by Macromedia. It can become all too easy to overlook the enhancements that are made to the existing features. Arrays and structures aren't new and sexy. <cfscript> they still make that? Sometimes you just get so used to doing things in a particular way that the enhancements aren't worth "re-learning" what you already know how to do. Or at least, that's what you might think.

When you're done "ooh-ing" and "aah-ing" over the new toys, take a few minutes to look at the old ones. Adobe polished them up while you were distracted. You just might like what you see.



You've been reading an excerpt of:

ColdFusion 8 Developer Tutorial

Explore Title