On page 548 of Blue Camel, it is written:
Perl provides the last operator so you can exit [a loop] in the
middle. Just "outdent" it to make it more visible:
LINE:
for (;;) {
statements;
last LINE if $foo;
next LINE if /^#/;
statements;
}
Note how last is outdented but next is not; why one
loop control statement and not the other? And what would be done if the
last were not conditionalled by an if modifier but
contained within an if block? Outdent the if, even
though the block probably contains other statements than the
last, probably unrelated to loop control? Outdent the
last all the way past the left margin of the for's
block, therefore beyond the left margin of the if?
Both of those options are terrible, and even though the outdent sort of works in the simple case given above, it could easily be misconstrued by someone unfamiliar with the convention as merely sloppy prettyprinting to be corrected, rather than as a "feature". This probable misinterpretation makes the convention less likely to be used, and the resulting obscurity makes it even less likely to be recognized.
Here's how I would prettyprint that block:
for (;;) {
statements;
; last if $foo;
; next if /^#/;
statements;
}
The leading semicolons always line up with the top keyword of
the control structure to which they apply, but the control
statements themselves are indented consistently with their
position in possibly-nested control structures. Note that
for (;;) {
statements;
if $foo {
statements;
; last;
}
; next if /^#/;
statements;
}
works just fine.
Using this convention in C++, I actually once had it detect a bug. A for was wrapped around an if...else if structure, with breaks inside the conditional. I later converted the conditional to a switch, so the breaks had become bogus. But the semicolons were still lined up with the control structure that the breaks had been intended to refer to, so as soon as I reread the code (before it was ever compiled) I spotted the error and converted the breaks to gotos.
In practice I find this coding technique robust enough that I don't need to use labels like LINE in the Blue Camel version on my fors. In the event that they are still desired, I'd suggest replacing
LINE:
for (;;) {
statements;
last LINE if $foo;
next LINE if /^#/;
statements;
}
with
LINE: for (;;) {
statements;
; last LINE if $foo;
; next LINE if /^#/;
statements;
}
to conform to what in Chapter 18 of
Code Complete
Steve McConnell calls the "Fundamental Theorem of Formatting": good visual
layout shows the logical structure of the code. Indenting the for
under the LINE implies that for is logically subordinate to
LINE, but it's not; it's at the same logical level. LINE
is the leading token of the control structure. Recognizing that "LABEL:
keyword" is the top of a control structure is relatively easy compared to
recognizing that "LABEL:\n{indent}keyword" is all the top of a control
structure. Also, it's less important that the leading token of the structure
be a keyword like for, since the semicolons always show what the
nested control statements were intended to apply to. The form in Blue Camel
takes an extra line of code and an extra level of indentation, neither of
which help show the logical structure of the code.