Gadi A
Gadi A

Reputation: 3539

For loop "jumps to the end" for no apparent reason?

In a Javascript program I have an object with the following two (simplified) functions:

this.do_A = function() {
    var nothing_changed = false;
    while (!nothing_changed) {
        nothing_changed = true;
        for (var column=0; column<this.columns; column++) {
            for (var row=0; row<this.rows; row++) {
                nothing_changed = nothing_changed && this.do_B(row, column);
            }
        }
    } 
}

this.do_B = function(row, column) {
    nothing_changed = true;
    if (this[row][column] == null) {
        nothing_changed = false;
    }
    return nothing_changed;
} 

When running this code something very strange happens when do_B returns false, and hence nothing_changed becomes false - when reaching again the

for (var row=0; row<this.rows; row++)

line, the row variable becomes immediately this.rows and hence the inner loop terminates. Moreover, it happens in the subsequent runs of the outer loops - row is initialized to be 0, then becomes this.rows immediately and the inner loop ends again.

I have no reason what can cause this. I have tried simplifying the functions as much as possible and it keeps happening.

Upvotes: 1

Views: 435

Answers (2)

wong2
wong2

Reputation: 35730

for (var row=0; row<this.rows; row++)
{
  nothing_changed = nothing_changed && this.do_B(row, column);
}  

When this.do_B(row, column) returns false, nothing_changed will be false , and when it loops again and reaches nothing_changed = nothing_changed && this.do_B(row, column), because nothing_changed is false, the second expression this.do_B(row, column) will not be evaluated, so nothing_changed will always be false until row reaches this.rows.

Upvotes: 6

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385194

How do you know the for loop jumps to the end? If you're checking by searching for invocations of do_B, then you need to account for the fact that in the following expression:

nothing_changed && this.do_B(row, column)

if nothing_changed is already false, then this.do_B(row, column) will not be called because, no matter what the RHS evaluates to, the expression as a whole will evaluate to false.

This is known as short-circuiting.

Perhaps that's what's going on? If you put debug output directly inside the for loop, I'm sure you'll see it continuing to the end of its prescribed number of iterations:

for (var column=0; column<this.columns; column++) {
  for (var row=0; row<this.rows; row++) {
    console.log(column + "|" + row);
    nothing_changed = nothing_changed && this.do_B(row, column);
  }
}

Upvotes: 0

Related Questions