I think the best solution is to use let
:
for (let i=0; i<100; i++) …
That will create a new (mutable) i
variable for each body evaluation and assures that the i
is only changed in the increment expression in that loop syntax, not from anywhere else.
I could kind of cheat and make my own generator. At least
i++
is out of sight :)
That should be enough, imo. Even in pure languages, all operations (or at least, their interpreters) are built from primitives that use mutation. As long as it is properly scoped, I cannot see what is wrong with that.
You should be fine with
function* times(n) {
for (let i = 0; i < n; i++)
yield i;
}
for (const i of times(5)) {
console.log(i);
}
But I don't want to use the
++
operator or have any mutable variables at all.
Then your only choice is to use recursion. You can define that generator function without a mutable i
as well:
function* range(i, n) {
if (i >= n) return;
yield i;
return yield* range(i+1, n);
}
times = (n) => range(0, n);
But that seems overkill to me and might have performance problems (as tail call elimination is not available for return yield*
).