Whatterz


Implicit Arrays in ColdFusion 8

by Simon. Average Reading Time: about a minute.

A great new feature of ColdFusion 8 is its new implicit creation of Arrays and Structures. In addition to the updates to operators in ColdFusion, those of you familiar with JavaScript will recognise and welcome these changes.

An array is a data structure consisting of a group of elements that are accessed by indexing. In most programming languages each element has the same data type. However, ColdFusion, as we will see, is not strictly typed and therefore allows any data type to be stored in combination. This allows strings, integers, booleans and other complex data types all to be stored in the same array. However, doing this certainly isnโ€™t a good practice as it causes signification complication when accessing the stored data.

Variables of a simple data type commonly only store a single value but, in some situations, it is useful to have a variable that can store a series of related values โ€“ using an array. Arrays are described as complex data types because they can hold data in a structured, complex way.

For example, suppose a routine is required that will calculate the average age among a group of six students. The ages of the students could be stored in six integer variables, added together and then divided by 6:

<cfscript>
age1 = 19;
age2 = 20;
age3 = 21;
age4 = 22;
age5 = 23;
age6 = 18;
 
average_age = (age1 + age2 + age3 + age4 + age5 + age6) / 6;
 
writeOutput(average_age); // returns 20.5
</cfscript>

However, a better solution would be to store the data in a six-element array and calculate the average age based upon the sum or the ages and the array length:

<cfscript>
age = arrayNew(1);
age[1] = 19;
age[2] = 20;
age[3] = 21;
age[4] = 22;
age[5] = 23;
age[6] = 18;
 
sum_age = 0;
 
//loop over the age array adding age together all ages
for (i = 1; i <= arrayLen(age); i++)
{
    sum_age += age[i];
}
 
//calculate the average age
average_age = sum_age / arrayLen(age);
 
writeOutput(average_age); // returns 20.5
</cfscript>

This is a few more lines of code, but allows for the flexibility of increasing or decreasing the number of elements (in this case ages) in the array, with no impact upon the core calculation.

NB: Unlike other programming languages, ColdFusion array indexes start from 1 not 0 (zero).

Implicit Arrays

With the introduction of implicit arrays in ColdFusion 8, the creation of arrays is greatly simplified. For example, rather than having to use the arrayNew(1) function, we can now simply do the following:

<cfscript>
myArray1 = [1,2,3]; //integers
</cfscript>

Implicit Arrays - Integer Example

This means that we can take the age calculation from ealier, and make the code even simpler to write:

<cfscript>
//implicity create the age array
age = [19,20,21,22,23,18];
 
sum_age = 0;
 
//loop over the age array adding age together all ages
for (i = 1; i <= arrayLen(age); i++)
{
    sum_age += age[i];
}
 
//calculate the average age
average_age = sum_age / arrayLen(age);
 
writeOutput(average_age); // returns 20.5
</cfscript>

Further examples

The following code snippets serve to exemplify my earlier comment that arrays can store any data type and indeed, any data type in combination.

Using strings:

<cfscript>
myArray2 = ["One","Two","Three"]; //strings
</cfscript>

Implicit Arrays - String Example

Using complex data types:

<cfscript>
myArray3 = [myArray1,myArray2]; //complex types (arrays)
</cfscript>

Implicit Arrays - Variables Example

Using implicit structures:

<cfscript>
myStruct1 = {firstname="Simon", lastname="Whatley", city="London"};
myStruct2 = {firstname="John", lastname="Doe", city="New York"};
myArray = [myStruct1, myStruct2];
</cfscript>

Implicit Arrays - Complex Example

The last two examples above serve to demonstrate that any complex data type can be used in conjuction with an array. This has not changed between ColdFusion version 7 and 8.

Mixing data types:

Although certainly not good practice, it is possible to mix the data types in an array. For example, we can use an Integer, String and Array as elements within an array, with no problem. However, it is when accessing this data that problems will arise.

<cfscript>
myArray4 = [1,"Two",myArray2];
</cfscript>

Implicit Arrays - Combined Example

Although the ColdFusion engine is not strict with regard to what data types are used within an array, always stick to the same type for each element.

Words of Caution

Implicit arrays do have their limitations. For example, you cannot nest implicit array, or indeed struct, creation.

<cfscript>
arrayOne = [
	arrayTwo = [1,2,3],
	arrayThree = [4,5,6]
]
</cfscript>

The above will throw the following parsing error:

coldfusion.compiler.ParseException:
Invalid CFML construct found on line 3 at column 13.

UPDATE: The recent ColdFusion Update now includes the ability to nest implicit arrays.

This article has been tagged

, , , , , , , , ,

Other articles I recommend

The Inner Workings of a ColdFusion Array and Structure

Array and Structures are considered to be complex data types in ColdFusion. In contrast, simple data types are ones that contain a single piece of data, such as an Integer, String, or Boolean value. A complex data type can contain multiple pieces of data, which, in the case of arrays, are usually related. All the data are referenced under a single variable name. You can think of a complex variable as a variable that contains a collection of other variables inside it. An array maps Integers to arbitrarily typed objects (Integers, Strings, Booleans and Objects) while a structure, or associative array, maps arbitrarily typed objects to arbitrarily typed objects.

Implicit Structures in ColdFusion 8

In an earlier post I eluded to the implicit creation of arrays in ColdFusion 8. Well, the same can be said of structures.

A structure, also known as an associative array, is a complex data type composed of a collection of keys and a collection of values, where each key is associated with one value (a key-value pair). The operation of finding the value associated with a key is called a lookup or indexing, and this is the most important operation supported by a structure. The relationship between a key and its value is sometimes called a mapping or binding. For example, if the value associated with the key “Age” is 29 and “City” is “London”, we say that our structure maps “Age” to 29 and “City” to “London”.

The Java Behind a ColdFusion Array and Structure

Following a conversation with a friend regarding how ColdFusion handles arrays and structures in ‘the background’, I was interested to find out what Java classes each were mapped to. This was a relatively simple case of using the functions getClass(), getSuperClass() and getName() to parse out the name of the Java classes.

  • http://youmuppet.com David Boyer

    Useful post :)

    I’ve run into the problem of nested arrays / structures using the new creation methods and decided to fall back to two functions of my own. I really think that Adobe should have tried to get nested creation working as it’d have been really useful for setting up more complex data structures.

    Here’s my alternatives that should work in CF7 too :)

    function Struct() {
    var lc = StructNew();
    lc.st = StructNew();
    for (lc.name in arguments) {
    lc.st[lc.name] = Duplicate(arguments[lc.name]);
    }
    return lc.st;
    }

    function Array() {
    var lc = StructNew();
    lc.a = ArrayNew(1);
    lc.count = ArrayLen(arguments);
    if (lc.count Gt 0) {
    for(lc.i = 1; lc.i Lt lc.count; lc.i = lc.i + 1) {
    lc.a[lc.i] = Duplicate(arguments[lc.i]);
    }
    }
    return lc.a;
    }

  • http://youmuppet.com David Boyer

    Forgot to add how to use them, d’oh!

    Struct(
    name = ‘bob’,
    clothes = Struct(
    hat = ‘bowler’,
    scarf = array(‘red’,’blue’,array(‘green’, ‘yellow’))
    )
    )

  • http://www.bennadel.com Ben Nadel

    Ben Forta announced that nested struct and array notation will *probably* be in the next ColdFusion 8 updater :)

    http://www.forta.com/blog/index.cfm/2008/2/29/Implicit-Array-And-Structure-Creation-Revisited

  • Dav

    I’d spotted that too. You also can’t directly feed an implicitly created Array or Struct into a function argument, such as
    ImageDrawText(myImage, someStr, x, y, {style=”bold”});

  • http://youmuppet.com David Boyer

    @Ben,

    Well spotted, nested creation that way would be almost as sexy as the pics you sometimes use on your site ๐Ÿ˜‰

    Now all I want sorted is named arguments for scoped functions and I’ll be a happy chappy

  • http://www.simonwhatley.co.uk Simon

    Instead of using the for-loop to calculate tha average values in the array, there is a little known function called ArrayAvg() that does it all for you. The function simply takes the name of the array and calculates the average of the values in the array.

    Thanks to Iain Turbitt for that suggestion.

  • http://blog.bpsite.net Peter Boughton

    I don’t like the CF8 syntax for this – just using symbols makes it harder to see at a glance what’s what.
    I much prefer the explicit Struct() and Array() functions which Railo has, and which can be created as David showed above … although there’s a much simpler way to write it than all that lc.st stuff…

  • http://blog.bpsite.net Peter Boughton

    <cffunction name=”Struct” returntype=”Struct”><cfreturn Arguments/></cffunction>

  • trev

    Thanks for a great tutorial
    For some reason I get an error on this code saying the cfscript tag needs to be closed. I can’t see why this cut and paste doesn’t work, using cfmx7 which at that part of the tutorial is fine I believe! Why do I get that error?

    age = arrayNew(1);
    age[1] = 19;
    age[2] = 20;
    age[3] = 21;
    age[4] = 22;
    age[5] = 23;
    age[6] = 18;

    sum_age = 0;

    //loop over the age array adding age together all ages
    for (i = 1; i <= arrayLen(age); i++)
    {
    sum_age += age[i];
    }

    //calculate the average age
    average_age = sum_age / arrayLen(age);

    writeOutput(average_age); // returns 20.5

  • trev

    my code does have the cfscript tags-when posting they were taken off!

  • http://www.simonwhatley.co.uk Simon

    The for loop uses the new to ColdFusion 8 javascript-style operators, which are not available in CF7.

    You will need to replace the for loop with:

    for (i = 1; i lte arrayLen(age); i=i+1)
    {

    }

  • trev

    thanks simon thought that looked new!! in the interests of cleaner code and my cf8 exam coming up soon I will do it all with cfscript but I think cfscript is a huge barrier for us people who come from a non programming background(cfloops are difficult to get my head around once I start having to add 1’s to curly brackets and use for instead of cfif then my brain seems to just switch off!!).

    Thanks again for pointing that out-another thing to learn now!!

  • alinmircea_s

    On a different note

    <cfscript>
    age = [19,20,21,22,23,18];
    </cfscript>
    <cfdump var=”#arrayavg(age)#”>
    there is also arraysum()

  • Paulsimo

    Would that be Iain turbitt from the wirral?

  • http://www.simonwhatley.co.uk/ Simon Whatley

    Nope. The Iain I refer to is from Belfast.