ColdFusion Bug: Arrays, ArrayLen(), And Implicit Structs

Posted March 26, 2009 at 1:55 PM by Ben Nadel

Tags: ColdFusion

I just ran up against a strange bug using ColdFusion arrays and implicit structs. I have experienced and read about several issues with implicit structs before and I would bet that this bug is falling under the same mechanism. The error occurs when I try to create an implicit struct and add it to an array at the same time. However, the bug only occurs if I get the array index of the insert based on the existing length of the array:

  • <!--- Define array. --->
  • <cfset arrData = [] />
  •  
  • <!--- Add struct to array. --->
  • <cfset arrData[ ArrayLen( arrData ) + 1 ] = { Foo = "Bar" } />

This throws the ColdFusion error:

The element at position 2 of dimension 1, of array variable "ARRDATA," cannot be found.

At first, I thought maybe there was something wrong with my indexing math; but, if you separate the calculation out into a separate line:

  • <!--- Define array. --->
  • <cfset arrData = [] />
  •  
  • <!--- Get next index. --->
  • <cfset intIndex = (ArrayLen( arrData ) + 1) />
  •  
  • <!--- Add struct to array. --->
  • <cfset arrData[ intIndex ] = { Foo = "Bar" } />

... it works just fine. I know I just read something recently on the order of operations that gets carried out with implicit structs, but I am not sure that this applies here as the error seems to be a function of the ArrayLen() evaluation.




Reader Comments

Mar 26, 2009 at 1:58 PM // reply »
11,314 Comments

FYI, this also errors with implicit arrays being stored as well.


Mar 26, 2009 at 2:29 PM // reply »
29 Comments

In addition to your second example actually working, I believe it is also more readable. I find this to be a better coding standard - one I try to follow, at least in other scripting languages. It is similar to looping over the length of an Array.

I would prefer this:

<cfset myArrayLen = ArrayLen(myArray) />

<cfloop from="1" to "#myArrayLen#" index="i">
....
</cfloop>

to this:

<cfloop from="1" to "#ArrayLen(myArray)#" index="i">
....
</cfloop>


Mar 26, 2009 at 2:32 PM // reply »
11,314 Comments

@Eric,

Ideally, what I would like to do is actually pass the implicit struct to the ArrayAppend() method:

<cfset ArrayAppend( arrData, { Foo = "Bar" } ) />

... but ColdFusion cannot support this yet. Hopefully in CF9, this improvement will be there. I think it's the best of both worlds.


Mar 26, 2009 at 2:34 PM // reply »
42 Comments

Hmm, for what you're doing there in the example, wouldn't it make more sense to use ArrayAppend()?

I'm not surprised CFML couldn't handle something like that. Have you tried the same code in CFScript? Somehow I think CFScript will work...


Mar 26, 2009 at 3:45 PM // reply »
39 Comments

Here's something weird:
<cfset arrData[ ArrayLen( arrData ) + 1 ] = "">

Does work for me, it's only when passing an implied structure that throws it off.

For me I use a simple function to get around this which also works as seen here:

<cffunction name="Echo" access="public" returntype="any" output="false" hint="Just returns the arguments passed to it.">
<cfreturn ARGUMENTS />
</cffunction>
<!--- Define array. --->
<cfset arrData = []>

<!--- Get next index. --->
<cfset arrData[ ArrayLen( arrData ) + 1 ] = Echo(Foo="Bar")>


Mar 26, 2009 at 3:57 PM // reply »
11,314 Comments

@Henry,

I have not tried this in Script, but I think it's a compile time error, not a runtime error. So, it may work in script, not sure.

@Tim,

Yeah, its a strange error. Implicit creation must be doing something rather odd.


Mar 26, 2009 at 4:19 PM // reply »
25 Comments

This is the same bug that I've blogged about several times. ColdFusion compiles this code:

<cfset a[arrayLen(a) + 1] = { foo = 2 } />

into this:

<cfset a[arrayLen(a) + 1] = structNew() />
<cfset a[arrayLen(a) + 1].foo = 2 />

This is a bug in ColdFusion's processing of struct literals, nothing to do with arrays. If you execute that code on Railo it'll work just dandy.


Mar 26, 2009 at 4:22 PM // reply »
11,314 Comments

@Barney,

Ahhh, you were the one who blogged about it! For some reason I thought it was Elliott Sprehn (I tried Googling it when it happened). Thanks for the clarification.


Mar 26, 2009 at 4:43 PM // reply »
25 Comments

Yeah, though I'm sure I'm not the only one. Everyone seems to run into it at some point. Here's the link to one of the posts. Neglected to put it in there the first time.

http://www.barneyb.com/barneyblog/2008/07/14/coldfusion-struct-literals-fail-again/


Jim
Mar 26, 2009 at 6:18 PM // reply »
16 Comments

Hi Ben,

I think you're right, it is a bug. It looks like the array is trying to reference the array at zero.

Try this code:

<cfset arrData = ['']>
<cfset arrData[(arrayLen(arrData)+1) - 1 ] = { Foo = "Bar" }>

<cfdump var="#arrData#"><cfabort>


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
Jun 20, 2013 at 6:56 AM
Experimenting With The Amazon Simple Storage Service (S3) API Using ColdFusion
" Meaning, if I PUT an object into S3, can I (as the PUT executer) read that object from S3 immediately? " "It depends" : http://aws.amazon.com/s3/faqs/#What_data_consistency_mo ... read »
Jun 20, 2013 at 3:15 AM
A Billion Wicked Thoughts By Ogi Ogas And Sai Gaddam
nice post i love it thanks 4 u :) ... read »
seb
Jun 20, 2013 at 2:32 AM
Working With Inherited Collections In AngularJS
@mike, @ben, The best article about scope and prototypal prototypical inheritance in angularjs is http://stackoverflow.com/questions/14049480/what-are-the-nuances-of-scope-prototypal-prototypical- ... read »
Jun 20, 2013 at 2:17 AM
ColdFusion NumberFormat() Exploration
Nice read thanks Ben, Is there a way to mask a negative number? Long story short in the finance sector when you go 'short' on a stock you want the price to fall this is a good thing because you are ... read »
Jun 20, 2013 at 1:09 AM
The Beauty Of The jQuery Each() Method
my html code : <html> <head> <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="nss.js"> ... read »
Jun 19, 2013 at 11:31 PM
Directive Link, $observe, And $watch Functions Execute Inside An AngularJS Context
@Ben, bunch to learn indeed, but thats fun part : ) ... read »
Jun 19, 2013 at 10:41 PM
Referencing ColdFusion Query Columns In A Loop Using Both Array And Dot Notation
Burdock-roots Are you going fat day by day? You need to be good for your family and make some money too. So we bring for you a best product that helps you to be more energetic every day. You will b ... read »
Jun 19, 2013 at 9:52 PM
Working With Inherited Collections In AngularJS
I recognize the applicability of your solution, and how easy it makes to share data across multiple views or even "submodules" of rather simple application. But it seems to me that it creat ... read »
InVision App - Prototyping Made Beautiful With Prototyping Tools