0

Given the code

var loops = 5;
var counter = 0;

function foo(counts){
    var baz = 0;
    for(var i=0;i<loops;i++){
        baz += i + counts;
    }
    return baz;
}

for(var i=0;i<foo(counter);i++){ //issue in this line
    console.log(i);
}

Every time that the for loop increments, it calls the foo function again.

Why is it doing this and is there a way to prevent this?

I understand that I can just store the return in a variable, but I'm still rather curious why this happens.

It doesn't happen in other languages like python.

The way I tested that it does this is by setting a breakpoint in the foo function.

Bigbob556677
  • 1,382
  • 1
  • 7
  • 25
  • `foo(counter)` calls foo until baz >= i as you ask it to. How is that a mystery? A for loop executes the test in between the ; ; each time – mplungjan Jul 22 '20 at 20:20
  • It's not a mystery that it calls it, but it calls it every time the loop runs. Instead of just once, and then using the returned value for each loop. Python does that. @mplungjan – Bigbob556677 Jul 22 '20 at 20:21
  • I doubt that. Anyway do `for(var i=0, n=foo(counter); i – mplungjan Jul 22 '20 at 20:22

2 Answers2

3

The stop condition is evaluate each iteration. If you want to evaluate only once do that:

var loops = 5;
var counter = 0;

function foo(counts){
    var baz = 0;
    for(var i=0;i<loops;i++){
        baz += i + counts;
    }
    return baz;
}

for(var i=0,l=foo(counter);i<l;i++){ //issue in this line
    console.log(i);
}
8HoLoN
  • 970
  • 1
  • 12
1

The equivalent python code would be

i = 0
while i < foo(counter):
    print(i)
    i++

That's just what a for loop does, the condition is evaluated before every iteration. If you want to call foo only once, you have to explicitly cache the result in a variable:

for (var i=0, n=foo(counter); i<n; i++) {
    console.log(i);
}

The (more pythonic) alternative would be to use an range generator (which is not available in the JS standard library though), where foo is called only once to create the iterator:

for (var i of range(0, foo(counter)) {
    console.log(i);
}
Bergi
  • 513,640
  • 108
  • 821
  • 1,164
  • @mplungjan Yeah, `n` is a better variable name than `len` :-) – Bergi Jul 22 '20 at 20:23
  • range is what i was using. Thank you. That makes sense, it was just hidden in the syntax. haha. The range generator is probably why it was only calling once. – Bigbob556677 Jul 22 '20 at 20:30
  • @Bigbob556677 Indeed. Python is not that different from JavaScript in regard to how the evaluation works, it's just that the idiomatic range loops use different approaches. – Bergi Jul 22 '20 at 20:50