Question

I've been looking at some old code at work and I've found several instances of nested loops in which the variable used for iterating over an object is re-assigned within the inner loop but it does not cause issues. For instance given the following example.cfm:

<cfscript>

    // Get every second value in an array of arrays
    function contrivedExampleFunction(required array data) {
        var filtered = [];

        for (i = 1; i lte arrayLen(arguments.data); i++) {
            var inner = arguments.data[i];

            for (i = 1; i lte arrayLen(inner); i++) {
                if (i eq 2) {
                    arrayAppend(filtered, inner);
                }
            }
        }

        return filtered;
    }

    data = [
        [1,2,3],
        [4,5,6],
        [7,8,9]
    ];

    // Expected (working function): [2, 5, 8]
    // Expected (short-circuiting): [2]
    // Actual result: [1, 2, 3]
    writeDump( contrivedExampleFunction(data) );

</cfscript>

I would expect the inner i declaration to re-assign the outer i and cause the function to 'short-circuit', especially as i isn't even scoped. However the function will return an unpredictable result. Why?

Was it helpful?

Solution

You're not desk-checking the code properly. It's wrong, but it works as expected.

The outer loop will loop i from 1-3
    First iteration i=1
    inner = data[1] => [1,2,3]
    The inner loop will loop i from 1-3
        First iteration i=1
            nothing to do
        Second iteration i=2
            append inner to filtered => [1,2,3]
        Third iteration i=3
            nothing to do
    end inner loop
    i=3, which meets the exit condition of the outer loop
end of outer loop

filtered = [1,2,3]

I think you are misreading this line of code:

arrayAppend(filtered, inner);

You're reading it as:

arrayAppend(filtered, inner[i]);

But it doesn't say that.

Make sense?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top