4

Based on Coldfusion documentation... "Arrays are passed to user-defined functions by value, so the function gets a new copy of the array data, and the array in the calling page is unchanged by the function."

So I'm working on a little practice project. I begin by taking a list of numbers, converting it to an array (which I call cardArray), then sorting the array, and finally passing the array to a couple UDFs that will look for various patterns in the numbers, and manipulate (if necessary) the argument (aka the passed array).

I never reference the original array in the UDFs, I only reference the argument name. Still... if I cfdump the original array after calling the functions, my original array has been altered. Can anyone tell me why?

I'm pretty sure I can work around this. Thus fixing this isn't my big problem. My problem is that this behaviour completely contradicts how I "thought" this would work, and it's driving me crazy!

    function hasPair(pairArray) {
        pairCount = 0;
        for (i=2; i lte arrayLen(pairArray); i++){
            if(pairArray[i] is pairArray[i-1]){
                pairCount++
                arrayDeleteAt(pairArray, i)
                arrayDeleteAt(pairArray, i-1)
                i=2
            }
        }
        return pairCount;
    }

    function hasStraight(straightArray){
        sequenceCards = 0;
        for (i=2; i lte arrayLen(straightArray); i++){
            if(straightArray[i] - straightArray[i-1] is 1){
                sequenceCards++
            }
        }
        if (sequenceCards GTE 4){
            return 1;
        }
        else{
            return 0;
        }
    }

</cfscript>

<cfoutput>
    <cfset cardList = "5,6,7,8,10,8,9">
    <cfset cardArray = listToArray(cardList)>
    <cfdump var="#cardArray#" label="Original Array Before">
    <cfset arraySort(cardArray, "numeric", "desc")>
     #hasPair(cardArray)# <br/> 
     #hasStraight(cardArray)# <br/> 
    <cfdump var="#cardArray#" label="Original Array After">
</cfoutput>

Results in:

Original array BEFORE function call [6,6,7,8,10,8,9].

Original array AFTER function call [10,9,7,6,5]

The array is sorted (which I expect, and is correct). However, the 8s are also missing. I did NOT expect this. The 8s are removed by the arrayDeleteAt(pairArray, i) and arrayDeleteAt(pairArray, i-1) methods in the first function. BUT this should be removing elements only from the array argument (pairArray), not the original array (or so I thought).

mts1701
  • 165
  • 6

2 Answers2

8

Since you have Lucee tagged here, I'm assuming you are running this on Lucee and not Adobe's implementation. Lucee does not conform to the Adobe spec in this case; arrays are passed by reference like all other complex objects.

Tim Jasko
  • 1,532
  • 1
  • 8
  • 12
  • Thank you so much. I did look extensively at Lucee documentation, but didn't find an explanation. Didn't think to look at specifically at differences from ACF. Thanks again. My mind is at peace again. – mts1701 Mar 09 '16 at 19:58
  • I wish I could have pulled up a more direct reference describing this behavior of Lucee, but that was all. FWIW, I think passing arrays by reference is the more sensible and consistent path, and Adobe seems to recognize this too, as they're adding the ability to do so to the latest CF. Alas, they're doing it as a global setting, instead of at the language level where it properly belongs. Classic Adobe. – Tim Jasko Mar 09 '16 at 21:15
  • Is this true for all versions of Lucee and Railo? Is there some way to request the ACF-compatible pass-by-value behavior, like ACF 2016 allows? – enigment Jun 12 '16 at 15:44
1

This can be pretty confusing, concerns structures also. Doing a <cfset arrayCopy = originalArray> and then modifying arrayCopy with some function will not guarantee the original array remains protected. The solution is to make a deep copy like this:

<cfset arrayCopy = Duplicate(originalArray)>
Presari
  • 106
  • 4
  • I would consider that correct behavior (and it matches most other languages). The array does not actually contain structures, it contains a bunch of references to structures, so when you copy it, you're copying the references. Both arrays are still pointing to the same underlying structs. – Tim Jasko Mar 10 '16 at 14:47
  • You're right, of course. I'll soften up my answer, no reason to blame coldfusion. – Presari Mar 10 '16 at 15:55