The Latest ColdFusion Mindƒµ©Ҝ

It's pretty common knowledge that ColdFusion passes arrays to UDF by value, and not by reference like pretty much every other language.  It's a weird behaviour, but as long as you remember to write array-processing functions to be used like this:

<cfset myArray = modifyArray(myArray) />

instead of like this:

<cfset modifyArray(myArray) />

you'll be fine.  However, someone pointed out on the Railo mailing list that this behaviour is not constrained to UDFs.  Assignment behave the same way!  Yes, if you assign an array to another variable, you get a copy.  The only "assignment" that is exempt from this behaviour is if you use structInsert.

Consider this code:

<cfset a = [37] />
<cfset a2 = a />
<cfset s1 = {array = a} />
<cfset s2 = {} />
<cfset s3 = {} />
<cfset s4 = {} />
<cfset s2.array = a />
<cfset s3["array"] = a />
<cfset structInsert(s4, "array", a) />
<cfset arrayAppend(a, 42) />
<cfset System = createObject("java", "java.lang.System") />
<p>#System.identityHashcode(a)# - #a.toString()#               <!--- [37, 42] --->
<p>#System.identityHashcode(a2)# - #a2.toString()#             <!--- [37]     --->
<p>#System.identityHashcode(s1.array)# - #s1.array.toString()# <!--- [37]     --->
<p>#System.identityHashcode(s2.array)# - #s2.array.toString()# <!--- [37]     --->
<p>#System.identityHashcode(s3.array)# - #s3.array.toString()# <!--- [37]     --->
<p>#System.identityHashcode(s4.array)# - #s4.array.toString()# <!--- [37, 42] --->

At the end of this code, there are five distinct arrays, one containing 37 and 42, and the other four containing only 37.  The blue lines create the four copies, and the red line creates a new "pointer" to the existing array.  Then when the green line executes the original array has 42 added to it, which only affects 'a' and 's4.array', because the rest are copies.

On Railo, arrays are universally reference types, so there would only be a single array in the above example.  This is consistent with most other languages.

Comments are closed.