ColdFusion structs Direct Assignment vs object literal notation

Literal notation is declarative programming, not procedural programming.

With literal notation, you tell the computer what it is you want clearly and in a single step. Without literal notation, you build what you want slowly, piece by piece, and without clarity.

Note that literal notation in CF8 is awkward and flawed, at best. It should rarely be used, and then only in simple cases. The literal notation in CF9 is fine.

For CF8, you can define helpers:

function $A() {
    var r = [ ];
    var i = 0;
    var m = ArrayLen(Arguments);
    for(i = 1; i <= m; i += 1)
        ArrayAppend(r, Arguments[i]);
    return r;
}
function $S() {
    return StructCopy(Arguments);
}

And use them as such:

var user = $S(
    Fname = "MyFirstnam",
    Lname = "MyLastName",
    titles = $A('Mr', 'Dr')
);

These helpers work all the time, preserve struct key case (struct keys are not simply uppercased but are cased as you typed them), and nest recursively without bound.


Before I tried anything, I thought straight away that literals would be faster, as you create everything you need in runtime, and don't need to waste time creating variables, then calling functions to append and all that.

I then wrote a little test that produces a chart with the results. You got me curious there :-)

The results prove I was right, as the graph shows a staggering difference as you can see: alt text

But remember that although one would jump and go with literal notation, I think it's important to remember that literal notation can be awkward, and will most of the times confuse more.

Obviously, if you are developing a page that really needs the speed boost, literal notation is what you're looking for, but be aware that sometimes on CF8, it will produce some strange behaviour.

Just to show you the sort of tests I run:

<cfset aLiterals = arrayNew(1) />
<cfset aDirect = arrayNew(1) />

<cfsilent>
    <cfloop from="1" to="10000" index="mm">

        <!--- LITERAL --->
        <!--- start timer --->
        <cfset start = getTickcount() />
        <cfloop from="1" to="1000" index="ii">  
            <cfset user = {Fname = "MyFirstnam", Lname = "MyLastName", titles = ['Mr','Dr']} />
        </cfloop>
        <!--- end timer --->
        <cfset end = getTickCount()>

        <!--- Display total time --->
        <cfset total = end-start>
        <cfset arrayAppend(aLiterals,total) />

        <!--- DIRECT --->
        <!--- start timer --->
        <cfset start1 = getTickcount() />
        <cfloop from="1" to="1000" index="jj">
            <cfset user = {} />
            <cfset user.Fname = "MyFirstnam" />
            <cfset user.Lname = "MyLastName" />
            <cfset user.titles = [] />
            <cfset ArrayAppend(user.titles,'Mr') />
            <cfset ArrayAppend(user.titles,'Dr.') />
        </cfloop>

        <!--- end timer --->
        <cfset end1 = getTickCount()>

        <!--- Display total time --->
        <cfset total1 = end1-start1>
        <cfset arrayAppend(aDirect,total1) />   
    </cfloop>
</cfsilent>

<!--- The cfchart --->
<cfchart format="png" xaxistitle="function" yaxistitle="Loading Time (in secs.)">
    <cfchartseries type="bar" serieslabel="literal">
        <cfchartdata item="literal" value="#arrayAvg(aLiterals)#">
    </cfchartseries>
    <cfchartseries type="bar" serieslabel="direct">
        <cfchartdata item="direct" value="#arrayAvg(aDirect)#">
    </cfchartseries>
</cfchart>

Hope this helps you.

Tags:

Coldfusion