As mentioned in the first code block, sometimes the loop will be terminated earlier after meeting the intention, but not in the other time, the loop is just a try, after which we need to do more tries. the for...else statement will make the intention express more concise.
Of course, a heavy logic of the loop statement separated to a function is better sometimes. . But the for...else... is still a good expression in much of time.
Yes, and it always exhausts the whole iterable, meaning it cannot be used with infinite iterables, or when you actually need to stop taking elements after the stop-condition.
I don't understand this confusion, but apparently it's common as some people struggle with it in Python as well. Here's how you should read it:
if (COND) THEN_BLOCK
else ELSE_BLOCK
// so far so good? ELSE_BLOCK runs when COND fails
while (COND) THEN_BLOCK
else ELSE_BLOCK
// this works exactly like the above, ELSE_BLOCK runs when COND fails,
// except here the COND and THEN_BLOCK may be evaluated more than once
for (INIT; COND; NEXT) THEN_BLOCK
else ELSE_BLOCK
// ELSE_BLOCK runs when COND fails
for (value of ITERABLE) THEN_BLOCK
else ELSE_BLOCK
// here you need to perform some mental gymnastics
// to figure out what the condition is;
// translates rougly to:
let value, done, iter = ITERABLE[Symbol.iterator];
while ({ value, done } = iter.next(), !done) THEN_BLOCK
else ELSE_BLOCK
// ELSE_BLOCK runs when the condition !done fails,
// i.e. when the iterable is exhausted
That being said, JS doesn't need else on loops, break from labelled block fulfils this role.
I'm with others in that a labelled block is better, and IMHO that idiom is a bit underused anyways (it's a structured goto, and do { ... } while (false) essentially just emulates a labelled block in a more boilerplatey and less immediately clear fashion).
I want to add that template engines (like Twig) also provide this construct and there it works very differently: There the else gets executed if no iterations happened because there were no items to loop over. So, IMO, if for ... else gets implemented, it should work like that. The other question is: is that necessary or any helpful? It would just replace if(foo.length === 0) { } with else { }, right?
If such a statement comes to exist, this IMHO is the right way to do it. Way easier to break out initially than later, and I find myself using one of these two patterns (with both for and while) way more than nested blocks or similar:
// 1. Check length first
if (list.length) {
for (let item of list) {
// enumerate item
}
} else {
// list empty
}
// 2. Check if loop body executed
let hasItems = false
for (let item of list) {
hasItems = true
// enumerate item
}
if (!hasItems) {
// list empty
}
Occasionally, if I'm coding a perf-sensitive bit and am working with iterables, I'll write out the desired loop manually:
let iter = set.values()
let result = iter.next()
if (result.done) {
// set empty
} else {
do {
let item = result.value
// enumerate item
result = iter.next()
} while (!result.done)
}
But in any case, it'd be super nice to just write it as this:
for (let item of list) {
// enumerate item
} else {
// list empty
}
Unfortunately else with loops can create problems with currently valid code.
Example:
if (true)
for (const v of []) console.log(v)
else console.log('nope')
In this code, with your proposal, else is supposed to be associated with the for loop but it is in fact currently valid code where else is associated with if.
I suggest to use another keyword, empty for example.
if (true)
for (const v of []) console.log(v)
else console.log('not true')
if (true)
for (const v of []) console.log(v)
empty console.log('array is empty')
The flaw in this code is that curly braces are omitted. After gotofail, I would have hoped that everyone had internalized that optional curly braces should always be explicitly present.
It's not always dangerous - for example, if you put the "if" and it's statement on the same line, there's not really any risk:
if (...) ...
Now the chances of someone squishing an if, for, and statement on the same line, then an else on the next line seems unlikely - unless that someone was a minified maybe?