Description
Cf. dart-lang/sdk#59148, where it is argued that else
should be avoided in the case where it has no effect (because the then-part always returns).
Arguably, less heavily indented code is easier to read than deeply indented code. For example:
void main() {
if (condition1) {
cleanupAsNeeded();
return something;
} else {
if (condition2) {
cleanupAsNeeded();
return something;
} else {
if (condition3) {
cleanupAsNeeded();
return something;
} else {
// Finally, the main case where everything was OK.
doTheRealWork();
}
}
}
// Versus ..
if (condition1) {
cleanupAsNeeded();
return something;
}
if (condition2) {
cleanupAsNeeded();
return something;
}
if (condition3) {
cleanupAsNeeded();
return something;
}
// Finally, the main case where everything was OK.
doTheRealWork();
}
The point is that the largest part of the code is performing various checks and potentially returning early (it could also have any other non-normal completion, e.g., throw something
, etc.), and it is quite easy to read those if-statements as "finish right here" constructs once we get the hang of it.
Of course, an early return may be successful or it may report a failure, but the point is that we know "if we go in here then we will end the execution of this function body, we won't reach the statements after this if
statement".
However, it might be useful for readability purposes if we made the status of those if-statements explicit:
void main() {
end if (condition1) {
cleanupAsNeeded();
return something;
}
end if (condition2) {
cleanupAsNeeded();
return something;
}
end if (condition3) {
cleanupAsNeeded();
return something;
}
// Finally, the main case where everything was OK.
doTheRealWork();
}
The choice of the word end
as a keyword (no need to make it built-in, it is immediately followed by a reserved word) is of course arbitrary. It could be return
(but that wouldn't match so well if it actually ends with throw something
), and it could be many other things. I'm just using end
here as a strawman.
It would be a compile-time error unless the then part of an end if
statement is guaranteed to return, throw, etc. (that is, unless it is guaranteed that it will not complete normally). We could allow an else
part, too, but it must again be guaranteed that it does not complete normally.
break
and continue
are somewhat tricky: Should we allow L: while (cond1) { end if (cond2) { break L; }}
? I would assume that it's so useful to be able to say that "end if
means that we stop running code in this function body", no exceptions, so that would probably be an error. Just delete end
if you wish to do that.
The point is that we get a very prominent visual representation of the fact that this if
statement must return, throw, etc., and this makes it easier to grasp what is going on when reading the code.
We could use a similar approach with loops: end while (cond) {...}
would signal that if we run the loop body at least once then it won't continue with the next statement, it will return/throw/etc. Similarly for switch
statements, and possibly some other constructs.