Discussion:
Add optional arguments to the break and continue statements
(too old to reply)
luserdroog
2016-11-10 02:28:28 UTC
Permalink
Raw Message
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
machine should break or continue /to/.

The argument could be a looping keyword (for, while, do) or
'switch'. For a switch in a for-loop, you can now write
`break switch;` to stay in the loop or `break for;` to get
out of it.

If a switch or loop is immediately preceeded by a 'label:',
then that label may also serve to designate /which loop/
in a nested set of loops.
Tom Allebrandi
2016-11-10 08:24:41 UTC
Permalink
Raw Message
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
Or, put a label at the targeted statement and use "goto label".

This

a) Explicitly documents where you were intending to go after a
break or continue;

b) Is immune to problems caused by adding or removing nesting;

c) Explicitly documents that you are making an "unnatural" change
in the flow of control;

d) Requires no change to the language.

--- tom
***@ytram.com
Keith Thompson
2016-11-10 16:28:43 UTC
Permalink
Raw Message
Post by Tom Allebrandi
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
Or, put a label at the targeted statement and use "goto label".
This
a) Explicitly documents where you were intending to go after a
break or continue;
b) Is immune to problems caused by adding or removing nesting;
c) Explicitly documents that you are making an "unnatural" change
in the flow of control;
d) Requires no change to the language.
There is existing practice in several languages (Ada and Perl for
example) for labelled break and continue statements or equivalent.

I think having the target label at the top of the loop or switch
statement makes for clearer code. For example:

THIS_LOOP:
while (1) {
/* ... */
if (condition) break THIS_LOOP;
}

Yes, it's equivalent to a goto (as all control structures ultimately
are), but logically you can think of the name THIS LOOP a referring to
the loop as a whole, rather than to a particular location in the code.
`break THIS_LOOP` breaks out of the loop; `goto END_OF_LOOP` branches to
a particular location in the code.

Assuming the above syntax, THIS_LOOP: could also be the target of a goto
statement, but disciplined programmers would (I hope) avoid using in
both roles.

Ada makes this more explicit. The syntax of a goto label is
<<NAME>>
(deliberately chosen to stand out and be ugly), while a label for a
block or loop is
NAME:

Perl, on the other hand, uses the same syntax for both.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jakob Bohm
2016-11-10 18:31:03 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Tom Allebrandi
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
Or, put a label at the targeted statement and use "goto label".
This
a) Explicitly documents where you were intending to go after a
break or continue;
b) Is immune to problems caused by adding or removing nesting;
c) Explicitly documents that you are making an "unnatural" change
in the flow of control;
d) Requires no change to the language.
There is existing practice in several languages (Ada and Perl for
example) for labelled break and continue statements or equivalent.
I think having the target label at the top of the loop or switch
while (1) {
/* ... */
if (condition) break THIS_LOOP;
}
Yes, it's equivalent to a goto (as all control structures ultimately
are), but logically you can think of the name THIS LOOP a referring to
the loop as a whole, rather than to a particular location in the code.
`break THIS_LOOP` breaks out of the loop; `goto END_OF_LOOP` branches to
a particular location in the code.
Assuming the above syntax, THIS_LOOP: could also be the target of a goto
statement, but disciplined programmers would (I hope) avoid using in
both roles.
Ada makes this more explicit. The syntax of a goto label is
<<NAME>>
(deliberately chosen to stand out and be ugly), while a label for a
block or loop is
Perl, on the other hand, uses the same syntax for both.
I seem to recall that some languages completely avoid the label by
simply allowing break/continue/etc. to specify the number of constructs
to exit to. For example "break 2". If (big if) that construct was to
be added to C, it should be a matter of serious thought if the count
specified with "continue" should also count the number of skipped
switch statements (so the number would be the same in a break statement
at the same location), of if it should only count the number of skipped
loops (so continue 1 is always the same as plain continue).

Either way, counting non-affectable statements, or counting from the
outermost function block would be problematic, as it would conflict
with routine code transformation practices such as adding redundant
braces as part of style-reindenting or to prepare for later changes, or
wrapping an outer loop around a large block of code.


Enjoy

Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded
BartC
2016-11-10 19:35:03 UTC
Permalink
Raw Message
Post by Jakob Bohm
Post by Keith Thompson
Ada makes this more explicit. The syntax of a goto label is
<<NAME>>
(deliberately chosen to stand out and be ugly), while a label for a
block or loop is
Perl, on the other hand, uses the same syntax for both.
I seem to recall that some languages completely avoid the label by
simply allowing break/continue/etc. to specify the number of constructs
to exit to. For example "break 2". If (big if) that construct was to
be added to C, it should be a matter of serious thought if the count
specified with "continue" should also count the number of skipped
switch statements
What on earth were the designers thinking to use same keyword to exit a
loop was what is routinely required inside 'switch'?
Post by Jakob Bohm
Either way, counting non-affectable statements, or counting from the
outermost function block would be problematic, as it would conflict
with routine code transformation practices such as adding redundant
braces
Mere braces shouldn't affect anything.

as part of style-reindenting or to prepare for later changes, or
Post by Jakob Bohm
wrapping an outer loop around a large block of code.
I use a scheme in another language (although I use 'exit' not 'break')
where:

break # means break out of this loop
break N # means break ouf of the Nth loop

Loops are counted from 1 for the innermost loop. 'break' is the same as
'break 1'.

However, I don't use break N very often, and then N usually corresponds
to the outermost loop. (And as loops three levels deep or more are
unusual, it's generally break 2.)

So perhaps all that's needed is:

break inner; # same as break, unless in switch then refers
# to the innermost loop
break outer; # break out of outermost loop

'inner' and 'outer' can be keywords that are shared with normal
identifiers as an identifier can never follow 'break'.

This should take care of the majority of cases where a multi-level loop
exit is needed.
--
Bartc
Keith Thompson
2016-11-10 20:25:26 UTC
Permalink
Raw Message
BartC <***@freeuk.com> writes:
[...]
Post by BartC
break inner; # same as break, unless in switch then refers
# to the innermost loop
break outer; # break out of outermost loop
'inner' and 'outer' can be keywords that are shared with normal
identifiers as an identifier can never follow 'break'.
This should take care of the majority of cases where a multi-level loop
exit is needed.
So we can add "break inner" and "break outer" to handle the majority of
cases, with serious problems when code is refactored and a loop is moved
into or out of another one (while also adding unreserved keywords,
something the language has never had before).

Or we can add "break label", one new construct rather than two, and
handle *all* cases in a way that's reasonably robust when code is
reorganized.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
BartC
2016-11-10 21:12:29 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by BartC
break inner; # same as break, unless in switch then refers
# to the innermost loop
break outer; # break out of outermost loop
'inner' and 'outer' can be keywords that are shared with normal
identifiers as an identifier can never follow 'break'.
This should take care of the majority of cases where a multi-level loop
exit is needed.
So we can add "break inner" and "break outer" to handle the majority of
cases, with serious problems when code is refactored and a loop is moved
into or out of another one (while also adding unreserved keywords,
something the language has never had before).
Or we can add "break label", one new construct rather than two, and
handle *all* cases in a way that's reasonably robust when code is
reorganized.
I don't think labeled loops solve all the problems of refactoring.

First, look at how break works now: you can wrap a loop around code that
currently has a switch-break, and change its meaning, or vice versa.

Or wrap a new loop around code that includes a loop break, turning one
loop into two, and now that break doesn't do the same job.

Any code that includes 'break label', where label is jumping out of two
loops or more, is not self-contained. The reason that 'break label'
exists might be specific to the original code. Extracting just that bit
into a new context might not be meaningful.

You would have to create a matching label, but the new location might
not have an outer loop. Or it might have two outer loops; which one to
apply it too? Or that label is already in use, at a different level of loop.

So it is full of problems anyway.

But if you don't like the idea of using loop indices or 'outer', then
another, for for-loops, could be to use the name of the loop-index
variable. Although the main problem there is that C doesn't have such a
concept (plus block scopes means the loop variable you want might be
shadowed). It would however remove the need to create labels.
--
Bartc
Keith Thompson
2016-11-10 21:27:13 UTC
Permalink
Raw Message
Post by BartC
Post by Keith Thompson
[...]
Post by BartC
break inner; # same as break, unless in switch then refers
# to the innermost loop
break outer; # break out of outermost loop
'inner' and 'outer' can be keywords that are shared with normal
identifiers as an identifier can never follow 'break'.
This should take care of the majority of cases where a multi-level loop
exit is needed.
So we can add "break inner" and "break outer" to handle the majority of
cases, with serious problems when code is refactored and a loop is moved
into or out of another one (while also adding unreserved keywords,
something the language has never had before).
Or we can add "break label", one new construct rather than two, and
handle *all* cases in a way that's reasonably robust when code is
reorganized.
I don't think labeled loops solve all the problems of refactoring.
I didn't say it did.
Post by BartC
First, look at how break works now: you can wrap a loop around code that
currently has a switch-break, and change its meaning, or vice versa.
If you wrap a loop around an existing switch-break, any break statements
still refer to the inner switch statement, not to the outer loop.
Post by BartC
Or wrap a new loop around code that includes a loop break, turning one
loop into two, and now that break doesn't do the same job.
It does the same job of breaking the innermost loop. If it instead
needs to break the outermost loop, then sure, you need to change the
code.
Post by BartC
Any code that includes 'break label', where label is jumping out of two
loops or more, is not self-contained. The reason that 'break label'
exists might be specific to the original code. Extracting just that bit
into a new context might not be meaningful.
Any code that includes "break label" almost certainly has some
logical connection to "label". If you take it out of the context
of that connection, then of course you're going to have to change
it so it works in the new context.
Post by BartC
You would have to create a matching label, but the new location might
not have an outer loop. Or it might have two outer loops; which one to
apply it too? Or that label is already in use, at a different level of loop.
So it is full of problems anyway.
Yeah, programming is hard. I don't see how labelled breaks make it
harder (and I've done a lot of programming in languages that provide
them).

Do you have a concrete example of the kind of problem you're describing?
Post by BartC
But if you don't like the idea of using loop indices or 'outer', then
another, for for-loops, could be to use the name of the loop-index
variable. Although the main problem there is that C doesn't have such a
concept (plus block scopes means the loop variable you want might be
shadowed). It would however remove the need to create labels.
Yes, the fact that there's no such thing makes it difficult to design a
language feature that depends on it. In any case, the logical construct
from which you want to break is the loop itself, not its index variable
if any. I like being able to refer to the loop by name.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
BartC
2016-11-10 22:03:47 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by BartC
First, look at how break works now: you can wrap a loop around code that
currently has a switch-break, and change its meaning, or vice versa.
If you wrap a loop around an existing switch-break, any break statements
still refer to the inner switch statement, not to the outer loop.
No, I meant inside a switch, but around code that includes break.
Admittedly that is unlikely if the code is properly structured (C allows
a chaotic structure to a switch).
Post by Keith Thompson
Yeah, programming is hard. I don't see how labelled breaks make it
harder (and I've done a lot of programming in languages that provide
them).
Do you have a concrete example of the kind of problem you're describing?
It's not me who has the problems! You said you don't like using implicit
numbering of nested loops because of all these issues.

I'm just saying that labels don't solve all of them. But also IME
dealing with more outer loops isn't that common. And there, usually you
want to quit the whole nest of loops so you don't really need an
explicit index or name.
Post by Keith Thompson
Post by BartC
But if you don't like the idea of using loop indices or 'outer', then
another, for for-loops, could be to use the name of the loop-index
variable. Although the main problem there is that C doesn't have such a
concept (plus block scopes means the loop variable you want might be
shadowed). It would however remove the need to create labels.
Yes, the fact that there's no such thing makes it difficult to design a
language feature that depends on it. In any case, the logical construct
from which you want to break is the loop itself, not its index variable
if any. I like being able to refer to the loop by name.
In Basic you used to write:

for i=1 to 10
...
next i

That's the kind of thing I meant. The 'i' identifies one particular
for-loop, so it doesn't need another identifier.
--
Bartc
Keith Thompson
2016-11-10 22:41:29 UTC
Permalink
Raw Message
[...]
Post by BartC
Post by Keith Thompson
Yes, the fact that there's no such thing makes it difficult to design a
language feature that depends on it. In any case, the logical construct
from which you want to break is the loop itself, not its index variable
if any. I like being able to refer to the loop by name.
for i=1 to 10
...
next i
That's the kind of thing I meant. The 'i' identifies one particular
for-loop, so it doesn't need another identifier.
In Basic, "next i" increments the value of i and jumps to the top of the
loop; that's why it refers to the name of the index variable. Basic is
not known for being well structured. (In the versions I've used, you
needed line numbers.)

That particular approach doesn't make sense in C.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Keith Thompson
2016-11-10 20:16:16 UTC
Permalink
Raw Message
Jakob Bohm <jb-***@wisemo.com> writes:
[...]
Post by Jakob Bohm
I seem to recall that some languages completely avoid the label by
simply allowing break/continue/etc. to specify the number of constructs
to exit to. For example "break 2". If (big if) that construct was to
be added to C, it should be a matter of serious thought if the count
specified with "continue" should also count the number of skipped
switch statements (so the number would be the same in a break statement
at the same location), of if it should only count the number of skipped
loops (so continue 1 is always the same as plain continue).
Sorry, but making the compiler force me to count levels is a *horrible*
idea. Think about refactoring code, changing the number of levels of
nesting, forgetting to change a 3 to a 2 somewhere, and getting no help
from the compiler.

Humans are usually pretty good at naming things. Computers are
*really* good at counting things.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
BartC
2016-11-10 22:19:09 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Jakob Bohm
I seem to recall that some languages completely avoid the label by
simply allowing break/continue/etc. to specify the number of constructs
to exit to. For example "break 2". If (big if) that construct was to
be added to C, it should be a matter of serious thought if the count
specified with "continue" should also count the number of skipped
switch statements (so the number would be the same in a break statement
at the same location), of if it should only count the number of skipped
loops (so continue 1 is always the same as plain continue).
Sorry, but making the compiler force me to count levels is a *horrible*
idea. Think about refactoring code, changing the number of levels of
nesting, forgetting to change a 3 to a 2 somewhere, and getting no help
from the compiler.
Humans are usually pretty good at naming things. Computers are
*really* good at counting things.
You've not driven on the autobahns in Germany? There, exits are named
rather than numbered as in the rest of western Europe.

That means when you've driven past one exit, you don't know whether you
missed yours some way back, or it is still to come. Unless you've
memorised the list of named junctions from the map.

But if you need exit 23 and you've just passed 21, then you can relax.
(Unless you're going the other way! But you will know if they're going
up or down.)

Same with house numbering. Or floor numbers and hotel rooms. Or streets
in the US. Or pages in the book ....

Now, this probably doesn't apply to numbered loops in program code,
unless you have dozens of such loops. Then it might take you a while to
find a particular named loop (unless they're in alphabetical order!).
But the principle of numbering such things is sound.
--
Bartc
Keith Thompson
2016-11-10 22:50:22 UTC
Permalink
Raw Message
Post by BartC
Post by Keith Thompson
[...]
Post by Jakob Bohm
I seem to recall that some languages completely avoid the label by
simply allowing break/continue/etc. to specify the number of constructs
to exit to. For example "break 2". If (big if) that construct was to
be added to C, it should be a matter of serious thought if the count
specified with "continue" should also count the number of skipped
switch statements (so the number would be the same in a break statement
at the same location), of if it should only count the number of skipped
loops (so continue 1 is always the same as plain continue).
Sorry, but making the compiler force me to count levels is a *horrible*
idea. Think about refactoring code, changing the number of levels of
nesting, forgetting to change a 3 to a 2 somewhere, and getting no help
from the compiler.
Humans are usually pretty good at naming things. Computers are
*really* good at counting things.
You've not driven on the autobahns in Germany? There, exits are named
rather than numbered as in the rest of western Europe.
That means when you've driven past one exit, you don't know whether you
missed yours some way back, or it is still to come. Unless you've
memorised the list of named junctions from the map.
But if you need exit 23 and you've just passed 21, then you can relax.
(Unless you're going the other way! But you will know if they're going
up or down.)
Same with house numbering. Or floor numbers and hotel rooms. Or streets
in the US. Or pages in the book ....
Now, this probably doesn't apply to numbered loops in program code,
unless you have dozens of such loops. Then it might take you a while to
find a particular named loop (unless they're in alphabetical order!).
But the principle of numbering such things is sound.
Autobahns? That's your argument?

Let's say we have an outer loop that iterates over a list of input
files, an intermediate loop that iterates over the lines in each file,
and an inner loop that iterates over characters. If you see a '!'
character, "ABORT", you want to abort all processing immediately. If
you see a '?' character, just abort the current file and continue with
the next.

I'm going to use pseudo-code to avoid distractions.

PROCESS_FILE_LIST:
foreach file {
PROCESS_ONE_FILE:
foreach line {
PROCESS_ONE_LINE:
foreach character {
if (current_character == '!') {
break PROCESS_FILE_LIST;
}
else if (current_character == '?') {
break PROCESS_ONE_FILE;
}
}
}
}

vs.

foreach file {
foreach line {
foreach character {
if (current_character == '!') {
break 3;
}
else {
break 2;
}
}
}
}

I know which one I'd rather write, read, or maintain.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
BartC
2016-11-10 23:55:38 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by BartC
Now, this probably doesn't apply to numbered loops in program code,
unless you have dozens of such loops. Then it might take you a while to
find a particular named loop (unless they're in alphabetical order!).
But the principle of numbering such things is sound.
Autobahns? That's your argument?
/Your/ argument was that humans are better with names than numbers. I
gave some counter-examples.
Post by Keith Thompson
Let's say we have an outer loop that iterates over a list of input
files, an intermediate loop that iterates over the lines in each file,
and an inner loop that iterates over characters. If you see a '!'
character, "ABORT", you want to abort all processing immediately. If
you see a '?' character, just abort the current file and continue with
the next.
I'm going to use pseudo-code to avoid distractions.
foreach file {
foreach line {
foreach character {
if (current_character == '!') {
break PROCESS_FILE_LIST;
}
else if (current_character == '?') {
break PROCESS_ONE_FILE;
}
}
}
}
vs.
foreach file {
foreach line {
foreach character {
if (current_character == '!') {
break 3;
}
else {
break 2;
}
}
}
}
I know which one I'd rather write, read, or maintain.
/* 3 */
foreach file {
/* 2 */
foreach line {
/* 1 */
foreach character {
if (current_character == '!') {
break 3;
}
else {
break 2;
}
}
}
}

Or:

#define PROCESSFILELIST 3
foreach file {
....
break PROCESSFILELIST;

etc if you like using names.

However I actually had some problem with the readability of your
labelled version. Partly your choice of names, as they are very similar.
But that can happen in real code too.

There are also issues about the placement of the labels: what are the
rules about how near to the loop they have to be? Can there be
intervening comments? Can they be next to the for-statement rather than
above it? (And will they share the same namespace as normal labels? Are
they in fact normal labels, which just happen to be before a for-statement?)

What happens if you break to a label that is not next to a
for-statement. What happens if you insert a new loop just after a loop
label? What happens if you wrap everything in a new loop except for the
label? Can people use macros for the break parameter, meaning having to
search the module to figure out which loop is being exited?

There's a simplicity about using constant indices. You know immediately
that 'break 1' is THIS loop; you don't need to search for a label name.
'break 2' is the next one out, etc. Or 'break outer' is the outermost.

Also, I have a problem with the idea of having to think up unique names
for every set of loops in a function. If there are multiple similar sets
of loops in a function (or in a program), all can use 'break 2' without
clashing. If loops are named, then you can't duplicate the loop
within the same function without renaming. Or if duplicating across
functions, the loop name may not be meaningful in the new function.

The indexing method is crude but is very easy and obvious to use, there
are fewer such questions as I raised above, and is simple to implement.
--
Bartc
Keith Thompson
2016-11-11 00:16:17 UTC
Permalink
Raw Message
Post by BartC
Post by Keith Thompson
Post by BartC
Now, this probably doesn't apply to numbered loops in program code,
unless you have dozens of such loops. Then it might take you a while to
find a particular named loop (unless they're in alphabetical order!).
But the principle of numbering such things is sound.
Autobahns? That's your argument?
/Your/ argument was that humans are better with names than numbers. I
gave some counter-examples.
My argument was in support of my statement that "break N" is a bad idea.
Your counterargument IMHO didn't address that.
Post by BartC
Post by Keith Thompson
Let's say we have an outer loop that iterates over a list of input
files, an intermediate loop that iterates over the lines in each file,
and an inner loop that iterates over characters. If you see a '!'
character, "ABORT", you want to abort all processing immediately. If
you see a '?' character, just abort the current file and continue with
the next.
I'm going to use pseudo-code to avoid distractions.
foreach file {
foreach line {
foreach character {
if (current_character == '!') {
break PROCESS_FILE_LIST;
}
else if (current_character == '?') {
break PROCESS_ONE_FILE;
}
}
}
}
vs.
foreach file {
foreach line {
foreach character {
if (current_character == '!') {
break 3;
}
else {
break 2;
}
}
}
}
I know which one I'd rather write, read, or maintain.
/* 3 */
foreach file {
/* 2 */
foreach line {
/* 1 */
foreach character {
if (current_character == '!') {
break 3;
}
else {
break 2;
}
}
}
}
#define PROCESSFILELIST 3
foreach file {
....
break PROCESSFILELIST;
etc if you like using names.
And you have to manually make sure that the value of your
PROCESSFILELIST macro matches the number of levels you want to break,
with no help from the compiler for typos.

Do you seriously like "break N" better than "break LABEL"?
Post by BartC
However I actually had some problem with the readability of your
labelled version. Partly your choice of names, as they are very similar.
But that can happen in real code too.
There are also issues about the placement of the labels: what are the
rules about how near to the loop they have to be? Can there be
intervening comments? Can they be next to the for-statement rather than
above it? (And will they share the same namespace as normal labels? Are
they in fact normal labels, which just happen to be before a for-statement?)
My answer to this is tentative, since this feature does not (yet?)
exist.

I'd say they're just normal labels. The syntax of a *labeled-statement*
(ignoring case and default) is:
identifier : statement
Labels can be stacked recursively:
label1: label2: label3: puts("Too many labels!");

If the statement, after stripping all labels, is either a loop statement
or a switch statement, any of the labels can be used in a "break label;"
statement. If it's a loop statement, it can be used in "continue label;".

One disadvantage is that the presence of a label permits the use of goto
statements. Ideally I'd like to use a different syntax for loop names
vs. goto labels, as Ada does, but goto labels already have the readable
lightweight syntax. (Sternly resisting the temptation to reuse the
"static" keyword.)
Post by BartC
What happens if you break to a label that is not next to a
for-statement. What happens if you insert a new loop just after a loop
label? What happens if you wrap everything in a new loop except for the
label? Can people use macros for the break parameter, meaning having to
search the module to figure out which loop is being exited?
I think the answers to all of these are straightforward given the rules
I've suggested.
Post by BartC
There's a simplicity about using constant indices. You know immediately
that 'break 1' is THIS loop; you don't need to search for a label name.
'break 2' is the next one out, etc. Or 'break outer' is the outermost.
Also, I have a problem with the idea of having to think up unique names
for every set of loops in a function.
You only need unique names when you're using multi-level breaks or
continues.
Post by BartC
If there are multiple similar sets
of loops in a function (or in a program), all can use 'break 2' without
clashing. If loops are named, then you can't duplicate the loop
within the same function without renaming. Or if duplicating across
functions, the loop name may not be meaningful in the new function.
The indexing method is crude but is very easy and obvious to use, there
are fewer such questions as I raised above, and is simple to implement.
Yes, it's crude; that's my objection. It seems designed to make things
just a little bit easier for the compiler by forcing the programmer to
do error-prone manual bookkeeping.

I remembered where I've seen this feature: it's in the Bourne shell.
I do a fair amount of shell scripting, and I've never used it.
I definitely have used the equivalent of "break label" in Perl.

If you think we can make any more progress in this debate, feel free to
respond, but I suspect we've taken it about as far as is likely to be
productive.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Thiago Adams
2016-11-11 11:31:51 UTC
Permalink
Raw Message
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
machine should break or continue /to/.
The argument could be a looping keyword (for, while, do) or
'switch'. For a switch in a for-loop, you can now write
`break switch;` to stay in the loop or `break for;` to get
out of it.
"The argument could be a looping keyword "
Do you mean the internal or external?

like this?

for ()
{
if ()
{
break for;
}
}

Another option, labeled for, while:


for loop1 ()
{
if ()
{
break loop1;
}
}


I think a new break for if also could be useful..

if labelif1 ()
{

if labelif2 ()
{

break else labelif1; //jump to else from first if

break labelif1; //jump to out if

}
else
{
}

}
else
{
}
Thiago Adams
2016-11-11 11:42:12 UTC
Permalink
Raw Message
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
machine should break or continue /to/.
The argument could be a looping keyword (for, while, do) or
'switch'. For a switch in a for-loop, you can now write
`break switch;` to stay in the loop or `break for;` to get
out of it.
C++ 17 had a recent modification on if .
if (init; condition)
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html

if now can have initializes, like for. Sharing just to show more stuffs to be considered.
BartC
2016-11-11 13:20:09 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
machine should break or continue /to/.
The argument could be a looping keyword (for, while, do) or
'switch'. For a switch in a for-loop, you can now write
`break switch;` to stay in the loop or `break for;` to get
out of it.
"The argument could be a looping keyword "
Do you mean the internal or external?
like this?
for ()
{
if ()
{
break for;
}
}
for loop1 ()
{
if ()
{
break loop1;
}
}
Those are good ideas. Better than adding an external label I think.

And 'for loop1 ...' looks more like the beginning of a conventional (ie.
non-C) for-loop with 'loop1' taking the role of the loop variable that
would identify the loop.

Perhaps there can also be:

break switch;

to further help disambiguate them. Also, when inside a for-loop inside a
switch, you might want 'break' to break out of the surrounding switch
not just the loop.
Post by Thiago Adams
I think a new break for if also could be useful..
if labelif1 ()
{
if labelif2 ()
Not too sure about these. But definitely 'while label ()' and 'do label ()'.
--
bartc
Kaz Kylheku
2016-11-11 13:57:21 UTC
Permalink
Raw Message
Post by BartC
Post by Thiago Adams
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
machine should break or continue /to/.
The argument could be a looping keyword (for, while, do) or
'switch'. For a switch in a for-loop, you can now write
`break switch;` to stay in the loop or `break for;` to get
out of it.
"The argument could be a looping keyword "
Do you mean the internal or external?
like this?
for ()
{
if ()
{
break for;
}
}
for loop1 ()
{
if ()
{
break loop1;
}
}
Those are good ideas. Better than adding an external label I think.
No new syntax is required for this. This is already C:

label: for (;;) {

}

the breaking out of labeled compound statements should be orthogonal to
other constructs.

In fact,

label: S

somewhere in a function, we can have it so that "break S" is possible
anywhere in the function, via an abstract syntax tree
transformation which resembles the following:

label: S -> { label: S label$after: ; }

break label; -> goto label$after;

Where label$after denotes a compiler-generated label associated with
label, which cannot clash with any other label.

So not only is this valid:

out: for (...) {
while (...) {
switch (...) {
...
break out;
}
}
}

but so is this:

{
if (condition)
break out;

out:
printf("condition is false\n");

// "break out;" jumps approximately here.
}

Thus "break label" just means "goto whatever statement follows the
labeled one (imagining there to be an empty one right after
it, if needed)". It's simply a companion to goto which aims slightly farther
down in the program.

There, I basically killed this issue.

It's a conforming extension to existing language which only due to the GCC
internals being a dog's breakfast can possibly take longer than 15
minutes to implement.

Furthermore, break; can be defined in terms of
"break label;"

for (;;) { break; } -> label$123: for (;;) { break label$123; }

That is to say, every switch or iteration statement can be considered
to be labeled uniquely, and break with no argument converts to a
break with an argument which is the label of the inner-most iteration
or switch.
BartC
2016-11-11 14:15:11 UTC
Permalink
Raw Message
Post by Kaz Kylheku
Post by BartC
Those are good ideas. Better than adding an external label I think.
label: for (;;) {
}
the breaking out of labeled compound statements should be orthogonal to
other constructs.
In fact,
label: S
somewhere in a function, we can have it so that "break S" is possible
anywhere in the function, via an abstract syntax tree
label: S -> { label: S label$after: ; }
break label; -> goto label$after;
Where label$after denotes a compiler-generated label associated with
label, which cannot clash with any other label.
out: for (...) {
while (...) {
switch (...) {
...
break out;
}
}
}
{
if (condition)
break out;
printf("condition is false\n");
// "break out;" jumps approximately here.
}
Thus "break label" just means "goto whatever statement follows the
labeled one (imagining there to be an empty one right after
it, if needed)". It's simply a companion to goto which aims slightly farther
down in the program.
There, I basically killed this issue.
By allowing it to be used as chaotically as 'goto'?

Now someone seeing 'break' no longer knows if it is just a switch-break
or loop-break, as it could be jumping anywhere.

With the danger also that if "out:" is perceived as a regular label,
someone might think it harmless to change the above to:

out:
++count;
printf("condition is false\n");

thus changing the behaviour.
Post by Kaz Kylheku
Furthermore, break; can be defined in terms of
"break label;"
for (;;) { break; } -> label$123: for (;;) { break label$123; }
That is to say, every switch or iteration statement can be considered
to be labeled uniquely, and break with no argument converts to a
break with an argument which is the label of the inner-most iteration
or switch.
That's how it has to work anyway. When I generate code, all loops have
up to four labels associated with them, to support break and continue
but also a couple more controls ['restart', 'redo', 'next' and 'exit'].

But in user code, you don't want to be dealing with either internal
labels, or explicit labels that are indistinguishable from labels usable
with goto. You just want the means to denote a specific loop.

That's why the 'for label ()' syntax was better than 'label: for ()'.
--
Bartc
s***@casperkitty.com
2016-11-11 19:21:10 UTC
Permalink
Raw Message
Post by BartC
Post by Kaz Kylheku
Thus "break label" just means "goto whatever statement follows the
labeled one (imagining there to be an empty one right after
it, if needed)". It's simply a companion to goto which aims slightly farther
down in the program.
There, I basically killed this issue.
By allowing it to be used as chaotically as 'goto'?
I fail to see the advantage to saying that exiting a loop should require
a label placed before the loop rather than after. I know Java decided to
use that pattern, but think that knowing where the control is actually
going is more useful than knowing the start of the loop which control is
leaving.
Thiago Adams
2016-11-11 19:46:51 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by BartC
Post by Kaz Kylheku
Thus "break label" just means "goto whatever statement follows the
labeled one (imagining there to be an empty one right after
it, if needed)". It's simply a companion to goto which aims slightly farther
down in the program.
There, I basically killed this issue.
By allowing it to be used as chaotically as 'goto'?
I fail to see the advantage to saying that exiting a loop should require
a label placed before the loop rather than after. I know Java decided to
use that pattern, but think that knowing where the control is actually
going is more useful than knowing the start of the loop which control is
leaving.
I agree.

Having to have labels is as bad/good as normal goto.

Alternatives?


for ()
{
for ()
{
//Normal
break;

//Not normal, breaks out external for
break for;

//Not normal, breaks out external for
break break;
}
}

If I had to choose I would choose
break break;
Jakob Bohm
2016-11-11 20:36:51 UTC
Permalink
Raw Message
Post by Thiago Adams
Post by s***@casperkitty.com
Post by BartC
Post by Kaz Kylheku
Thus "break label" just means "goto whatever statement follows the
labeled one (imagining there to be an empty one right after
it, if needed)". It's simply a companion to goto which aims slightly farther
down in the program.
There, I basically killed this issue.
By allowing it to be used as chaotically as 'goto'?
I fail to see the advantage to saying that exiting a loop should require
a label placed before the loop rather than after. I know Java decided to
use that pattern, but think that knowing where the control is actually
going is more useful than knowing the start of the loop which control is
leaving.
I agree.
Having to have labels is as bad/good as normal goto.
Alternatives?
for ()
{
for ()
{
//Normal
break;
//Not normal, breaks out external for
break for;
//Not normal, breaks out external for
break break;
}
}
If I had to choose I would choose
break break;
Suggested simplification (if this idea is to be entertained at all):

break: Breaks out first level, as today
break for: Breaks out of innermost for, which may or may not be
innermost breakable construct
break while: Breaks out of innermost while or do-while, which may or may
not be innermost breakable construct
break switch: Breaks out of innermost switch, which may or may not be
innermost breakable construct.
break for for breaks out of the second-innermost for loop
break while for breaks out of the innermost for loop that incapsulates
the innermost while loop.
break break: breaks out of the second-innermost breakable construct.
etc.

Similarly for continue;

Additionally:

return statements still exit all levels directly.

goto label can still enter and exit levels arbitrarily (unlike in early
variants of C++).

continue switch: NOP bust must occur directly before a case label in a
switch statement, no meaning assigned to deeper variants. If an
implementation issues a diagnostic when a statement other than
break/continue/goto/return/exit()/abort() etc. is followed by a case
label, the "continue switch" line suppresses that diagnostic by
indicating a deliberate fall-through, similar to the historic
annotations used by tools such as lint. (So no new invention for this
particular case).

Notice how a "break switch" is completely immune to the placement of
loops and similarly for the other types. Also notice how the less
usual actions have the longer syntax.

Enjoy

Jakob
--
Jakob Bohm, CIO, Partner, WiseMo A/S. https://www.wisemo.com
Transformervej 29, 2860 Søborg, Denmark. Direct +45 31 13 16 10
This public discussion message is non-binding and may contain errors.
WiseMo - Remote Service Management for PCs, Phones and Embedded
Keith Thompson
2016-11-11 21:38:00 UTC
Permalink
Raw Message
Thiago Adams <***@gmail.com> writes:
[...]
Post by Thiago Adams
Having to have labels is as bad/good as normal goto.
Only if the label is just a name for a location in the code.

*All* control constructs can be reduced to labels and gotos. The reason
we use if, for, while, et al is that they impose structure and avoid
chaos. (Switch is still pretty chaotic, but it can be used with some
discipline.)

At the risk of repeating myself, the solution I advocate is to add a
label to the top of a loop (perhaps just after the keyword). That label
is the name of the entire loop. "break foo" or "continue foo" would be
defined in terms similar to a goto, but the meaning is that it applies
to the loop.

I've worked in languages that have similar constructs, and I've found
that it works very well.
Post by Thiago Adams
Alternatives?
for ()
{
for ()
{
//Normal
break;
//Not normal, breaks out external for
break for;
//Not normal, breaks out external for
break break;
}
}
If I had to choose I would choose
break break;
Are you saying that "break for;" would break out of the *outer* for
loop, not the inner one? What if you have a "break for;" that's only
within a single for statement?

Would you use "break break break;" to break out of 3 levels of loop?
That's even worse than "break 3;".

With the scheme I'm advocating, this might look like:

for OUTER (;;) {
for INNER (;;) {
if (this) break; // terminates inner loop
if (that) break INNER; // terminates inner loop
if (the_other) break OUTER; // terminates outer loop
}
}

I know that each break statements transfers control to a particular
point in the code, but I don't need to care. I care which loop is being
terminated.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Keith Thompson
2016-11-11 20:34:56 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by BartC
Post by Kaz Kylheku
Thus "break label" just means "goto whatever statement follows the
labeled one (imagining there to be an empty one right after
it, if needed)". It's simply a companion to goto which aims slightly farther
down in the program.
There, I basically killed this issue.
By allowing it to be used as chaotically as 'goto'?
I fail to see the advantage to saying that exiting a loop should require
a label placed before the loop rather than after. I know Java decided to
use that pattern, but think that knowing where the control is actually
going is more useful than knowing the start of the loop which control is
leaving.
The advantage is that the argument to the "break" statement is the name
of the loop, not the location in the code you want to branch to.

The whole idea of structure programming, IMHO, is that constructs in
code correspond to concepts in the problem domain. An if statement
corresponds to a decision. A loop corresponds to a repeated action.
A label that can be the target of a goto corresponds only to a
point in the code, not to anything in the problem domain.

If I can give a loop a meaning name, then "break name_of_loop" means
"stop doing the meaningful task this loop is doing".
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Keith Thompson
2016-11-11 16:16:49 UTC
Permalink
Raw Message
Thiago Adams <***@gmail.com> writes:
[...]
Post by Thiago Adams
for loop1 ()
{
if ()
{
break loop1;
}
}
[...]

I like it. Currently an identifier can't appear after "for", "while",
or "do", so it won't break existing code. And it avoids using goto
labels.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Philip Guenther
2016-11-11 23:33:31 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Thiago Adams
for loop1 ()
{
if ()
{
break loop1;
}
}
[...]
I like it. Currently an identifier can't appear after "for", "while",
or "do", so it won't break existing code. And it avoids using goto
labels.
That works for 'for' and 'while', but 'do' can be followed by an identifier:
do
ret = foo(input);
while (ret != 0);

Need more look ahead to see whether it's followed by a colon or not.

...or keep the label after the 'while' in a do/while loop, ala:

do {
for (...) {
if (cond)
break outer;
}
} while outer (ret != 0);

Labels for goto aren't forward declared, so compilers are clearly able to handle that sort thing.


Philip Guenther
Keith Thompson
2016-11-12 00:56:27 UTC
Permalink
Raw Message
Post by Philip Guenther
Post by Keith Thompson
[...]
Post by Thiago Adams
for loop1 ()
{
if ()
{
break loop1;
}
}
[...]
I like it. Currently an identifier can't appear after "for", "while",
or "do", so it won't break existing code. And it avoids using goto
labels.
do
ret = foo(input);
while (ret != 0);
Good point. (I always use braces, but I'm not going to suggest
requiring them.)
Post by Philip Guenther
Need more look ahead to see whether it's followed by a colon or not.
do {
for (...) {
if (cond)
break outer;
}
} while outer (ret != 0);
Labels for goto aren't forward declared, so compilers are clearly able
to handle that sort thing.
Sure, compilers can handle it, but putting the label at the end of the
loop (and only for one kind of loop) defeats the purpose as far as I'm
concerned.

We could fall back to using existing goto labels, where a label name can
be used in "break name" only if it labels a loop or switch statement.
Or we can invent a new syntax that's unambiguous.

One thought (that I'm not sure I particularly like) is:

:LABEL: do {
...
break LABEL;
} while (condition);
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Philip Lantz
2016-11-12 02:21:12 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Philip Guenther
Post by Keith Thompson
[...]
Post by Thiago Adams
for loop1 ()
{
if ()
{
break loop1;
}
}
[...]
I like it. Currently an identifier can't appear after "for", "while",
or "do", so it won't break existing code. And it avoids using goto
labels.
do
ret = foo(input);
while (ret != 0);
Good point. (I always use braces, but I'm not going to suggest
requiring them.)
I don't always use braces, but I wouldn't object to requiring them when
a label is needed. I think that would be better than the ideas you
suggested to avoid it.
Richard Kettlewell
2016-11-12 11:56:45 UTC
Permalink
Raw Message
Post by Keith Thompson
We could fall back to using existing goto labels, where a label name can
be used in "break name" only if it labels a loop or switch statement.
Or we can invent a new syntax that's unambiguous.
:LABEL: do {
...
break LABEL;
} while (condition);
What’s the benefit of using a new label syntax? It seems like a
completely arbitrary extra bit of complexity.
--
http://www.greenend.org.uk/rjk/
BartC
2016-11-12 13:33:45 UTC
Permalink
Raw Message
Post by Richard Kettlewell
Post by Keith Thompson
We could fall back to using existing goto labels, where a label name can
be used in "break name" only if it labels a loop or switch statement.
Or we can invent a new syntax that's unambiguous.
:LABEL: do {
...
break LABEL;
} while (condition);
What’s the benefit of using a new label syntax? It seems like a
completely arbitrary extra bit of complexity.
Because it's not a label. It doesn't behave like a regular label. And
you don't want it to used with 'goto'.
--
Bartc
Richard Kettlewell
2016-11-12 14:31:59 UTC
Permalink
Raw Message
Post by BartC
Post by Richard Kettlewell
Post by Keith Thompson
We could fall back to using existing goto labels, where a label name can
be used in "break name" only if it labels a loop or switch statement.
Or we can invent a new syntax that's unambiguous.
:LABEL: do {
...
break LABEL;
} while (condition);
What’s the benefit of using a new label syntax? It seems like a
completely arbitrary extra bit of complexity.
Because it's not a label. It doesn't behave like a regular label.
That’s the question, not the answer: should it be a regular label or
not?
Post by BartC
And you don't want it to used with 'goto'.
Why not?
--
http://www.greenend.org.uk/rjk/
BartC
2016-11-12 15:30:10 UTC
Permalink
Raw Message
Post by Richard Kettlewell
Post by BartC
Post by Richard Kettlewell
Post by Keith Thompson
We could fall back to using existing goto labels, where a label name can
be used in "break name" only if it labels a loop or switch statement.
Or we can invent a new syntax that's unambiguous.
:LABEL: do {
...
break LABEL;
} while (condition);
What’s the benefit of using a new label syntax? It seems like a
completely arbitrary extra bit of complexity.
Because it's not a label. It doesn't behave like a regular label.
That’s the question, not the answer: should it be a regular label or
not?
Because the intended behaviour is different. Execution after break or
continue usually doesn't pass to the statement following that label (and
they will necessarily have to end up at different places).
Post by Richard Kettlewell
Post by BartC
And you don't want it to used with 'goto'.
You don't want to encourage gotos and labels. We want to introduce a new
higher level feature not another low level one.

If you don't want to change anything, just stipulate that the label for
break must immediately follow the loop statement, and use goto. Or goto
dressed up as a macro. And a different loop placement for 'continue'.

But that's what we have now. I guess it's not satisfactory otherwise we
wouldn't have this thread.

(What does C++ do? That's a language keener to adopt new ideas. But then
new syntax such as this is rarely popular so I wouldn't be surprised if
it didn't have multi-level loop controls. The chances of C getting it
would then be zero.)
--
Bartc
Kaz Kylheku
2016-11-13 04:18:21 UTC
Permalink
Raw Message
Post by BartC
You don't want to encourage gotos and labels. We want to introduce a new
higher level feature not another low level one.
LOL!

A break isn't a higher level feature relative to goto; it's a form of
goto with a few restrictions (which, as I illustrated, don't actually
have to exist in order to support the intended use).
Keith Thompson
2016-11-13 05:09:28 UTC
Permalink
Raw Message
Post by Kaz Kylheku
Post by BartC
You don't want to encourage gotos and labels. We want to introduce a new
higher level feature not another low level one.
LOL!
A break isn't a higher level feature relative to goto; it's a form of
goto with a few restrictions (which, as I illustrated, don't actually
have to exist in order to support the intended use).
It's the restrictions that make it a higher level feature.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
s***@casperkitty.com
2016-11-13 05:30:10 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Kaz Kylheku
A break isn't a higher level feature relative to goto; it's a form of
goto with a few restrictions (which, as I illustrated, don't actually
have to exist in order to support the intended use).
It's the restrictions that make it a higher level feature.
Restrictions on the use of language functions are helpful when they allow
allow a compiler or a programmer to infer things that they could not readily
infer otherwise. Someone who sees that a "goto" is performed within a loop
and jumps to a point past the end of the loop could readily infer that the
goto is leaving the loop in question. I'm not sure what additional info the
described syntax could provide.
Keith Thompson
2016-11-13 10:42:27 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Keith Thompson
Post by Kaz Kylheku
A break isn't a higher level feature relative to goto; it's a form of
goto with a few restrictions (which, as I illustrated, don't actually
have to exist in order to support the intended use).
It's the restrictions that make it a higher level feature.
Restrictions on the use of language functions are helpful when they allow
allow a compiler or a programmer to infer things that they could not readily
infer otherwise. Someone who sees that a "goto" is performed within a loop
and jumps to a point past the end of the loop could readily infer that the
goto is leaving the loop in question. I'm not sure what additional info the
described syntax could provide.
The idea is that the label is the name of the loop. You can think
of it as jumping to the point in the code where the label is (which
happens to be at the end of the loop), or it can refer to the loop
itself as a higher-level construct.

It's a direct statement that we're breaking out of this loop,
rather than a goto that just happens to jump to that point --
and that could be targeted by another goto anywhere in the function.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Kaz Kylheku
2016-11-13 18:33:55 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by s***@casperkitty.com
Post by Keith Thompson
Post by Kaz Kylheku
A break isn't a higher level feature relative to goto; it's a form of
goto with a few restrictions (which, as I illustrated, don't actually
have to exist in order to support the intended use).
It's the restrictions that make it a higher level feature.
Restrictions on the use of language functions are helpful when they allow
allow a compiler or a programmer to infer things that they could not readily
infer otherwise. Someone who sees that a "goto" is performed within a loop
and jumps to a point past the end of the loop could readily infer that the
goto is leaving the loop in question. I'm not sure what additional info the
described syntax could provide.
The idea is that the label is the name of the loop.
This is not significantly higher level than the concept that foo: <s>
makes foo the name of statement S.

(As we are all here aware, C requires a label to be followed by a
statement, and that effectively ties the label to the statement as its
name.)

C's goto is already significantly high level feature; it is
approximately on par with for, while, do/while and if, along with
break and continue.
Post by Keith Thompson
You can think
of it as jumping to the point in the code where the label is (which
happens to be at the end of the loop), or it can refer to the loop
itself as a higher-level construct.
It's a direct statement that we're breaking out of this loop,
rather than a goto that just happens to jump to that point --
and that could be targeted by another goto anywhere in the function.
That restriction just cripples the feature in a trivial way.

There is no technical reason for the restriction alone, because goto is
already safe. (goto itself has considerable restrictions, and they have
to do with real issues of safety and ease of implementation; they
are not just trivially crippling restrictions on top of a working mechanism
that could easily support something more general.)

If a loop has a name, and you don't think that statemenets outside of
that loop shuld be able to branch to that loop by issuing a goto against
that name, then you can simply just not do that, or lobby your compiler
vendor to provide an optional warning for that usage.

Here is how you can actually make this a higher level feature: put the
labels into their own namespace and allow them to be re-used among
separate and nested loops:

for same_name (...) {
for same_name (...) { // OK
break same_name; // refers to inner-most same_name
}
}

for same_name (...) { // OK

}

same_name: ; // OK, different namespace

same_name: ; // Error.

Now we're technically justified in not allowing "goto same_name":
there are potentially multiple targets, and they are in a separate
namespace anyway.
BartC
2016-11-13 19:05:17 UTC
Permalink
Raw Message
Post by Kaz Kylheku
Post by Keith Thompson
The idea is that the label is the name of the loop.
This is not significantly higher level than the concept that foo: <s>
makes foo the name of statement S.
(As we are all here aware, C requires a label to be followed by a
statement, and that effectively ties the label to the statement as its
name.)
Actually, a label can be followed by another label. Only the last needs
to be followed by a statement. So we can have:

L1: L2: L3: ... <s>

Then S can have any number of different names. That's one difference
from a proposed loop-label.

Furthermore, S can be the empty statement ";". Another difference as a
loop label must refer to a loop.
Post by Kaz Kylheku
C's goto is already significantly high level feature; it is
approximately on par with for, while, do/while and if, along with
break and continue.
Most people would disagree I think. The only difference between C's goto
and ASM's 'jump' is that you can't jump outside of a function, and you
can't jump into the middle of an expression.
Post by Kaz Kylheku
Post by Keith Thompson
It's a direct statement that we're breaking out of this loop,
rather than a goto that just happens to jump to that point --
and that could be targeted by another goto anywhere in the function.
That restriction just cripples the feature in a trivial way.
If a loop has a name, and you don't think that statemenets outside of
that loop shuld be able to branch to that loop by issuing a goto against
that name, then you can simply just not do that,
/We/ can, but what about anyone else?
Post by Kaz Kylheku
Here is how you can actually make this a higher level feature: put the
labels into their own namespace and allow them to be re-used among
for same_name (...) {
for same_name (...) { // OK
break same_name; // refers to inner-most same_name
}
}
for same_name (...) { // OK
}
same_name: ; // OK, different namespace
same_name: ; // Error.
there are potentially multiple targets, and they are in a separate
namespace anyway.
This is pretty much what is being discussed. Being able to reuse the
same loop label name would be another advantage if loop labels and
ordinary labels are distinct.

Using the same name for a loop label and an ordinary label would be
confusing, but this can be one of those things that can be advised against.

(C labels, with their own namespace, can already have the same names as
variables, types, structs and enums in the same scope. Why anyone ever
thought that would be a good idea, I haven't got a clue. Fortunately I
guess not many know about it as you don't see it often!)
--
Bartc
Kaz Kylheku
2016-11-13 19:43:18 UTC
Permalink
Raw Message
Post by BartC
Post by Kaz Kylheku
Post by Keith Thompson
The idea is that the label is the name of the loop.
This is not significantly higher level than the concept that foo: <s>
makes foo the name of statement S.
(As we are all here aware, C requires a label to be followed by a
statement, and that effectively ties the label to the statement as its
name.)
Actually, a label can be followed by another label. Only the last needs
L1: L2: L3: ... <s>
W00T?

Were you playing hooky when recursive definitions were covered?

ISO C99:

(6.8) statement:
labeled-statement
[... other kinds ...]


(6.8.1) labeled-statement:
identifier : statement
case constant-expression : statement
default : statement

A labeled-statement can be "identifier : statement", where "statement"
can be a "labeled-statement".

Your L1: labels a labeled-statement, producing a new labeled-statement.
BartC
2016-11-13 20:02:43 UTC
Permalink
Raw Message
Post by Kaz Kylheku
Post by BartC
Actually, a label can be followed by another label. Only the last needs
L1: L2: L3: ... <s>
W00T?
Were you playing hooky when recursive definitions were covered?
labeled-statement
[... other kinds ...]
identifier : statement
case constant-expression : statement
default : statement
A labeled-statement can be "identifier : statement", where "statement"
can be a "labeled-statement".
Your L1: labels a labeled-statement, producing a new labeled-statement.
The end result, which is what matters, is that the same executable
statement can be addressed by multiple different labels.

It allows extra variety, when using 'goto' to emulate more elaborate
breaks and continues, that is IMO undesirable.
--
Bartc
s***@casperkitty.com
2016-11-13 22:03:44 UTC
Permalink
Raw Message
Post by BartC
Post by Kaz Kylheku
Post by BartC
Actually, a label can be followed by another label. Only the last needs
L1: L2: L3: ... <s>
W00T?
Were you playing hooky when recursive definitions were covered?
labeled-statement
[... other kinds ...]
identifier : statement
case constant-expression : statement
default : statement
A labeled-statement can be "identifier : statement", where "statement"
can be a "labeled-statement".
Your L1: labels a labeled-statement, producing a new labeled-statement.
The end result, which is what matters, is that the same executable
statement can be addressed by multiple different labels.
It allows extra variety, when using 'goto' to emulate more elaborate
breaks and continues, that is IMO undesirable.
When required business logic fits pre-defined control structures, it is
almost always better to use those control structures than to synthesize
them using "goto". In cases where the business logic does not fit such
the built-in control structures, it's often better to make the design of
the program match the design of the business logic--even if that means
using gotos--than to try to contort both the business logic and the
language's control structures in an effort to make them fit.

If there are multiple ways via which execution might reach a certain
point, having multiple labels for the different ways may help to make
that clear. More importantly, having multiple labels is helpful in
cases where e.g. one goto is performed before a code performs an
action which doesn't presently require cleanup but might require it
in future, and another goto is performed after that action. If it
is necessary to add cleanup logic, it would go between the two labels.
If both gotos had targeted the same same label, it would not be possible
to add cleanup logic between their targets.

While I have certainly found the inability to break out of a loop from
within a switch statement annoying, there are enough other patterns which
don't quite fit a language's looping structures that if a language
supports goto it would be the most logical approach. Consider, for
exampe, the scenario where a function needs to loop to find something and
then act upon the item; if the item isn't found, the function should quit.
While one could nest within the loop all the code that should execute when
the item is found, such placement would suggest that such code would expect
to be executed more than once. Having failure-exit logic following the
loop and a label beyond, and having the success case goto that label will
IMHO better fit the business logic than would burying the success code
within the loop or using some quirky "while(condition || ((error_flag=1),0)`
loop. Some other languages allow loops to have an "else" clause, but
adding such a thing to C would break code since it would cause an "else"
that follows a loop to bind to that loop rather than an outer "if".
BartC
2016-11-14 11:53:24 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
While I have certainly found the inability to break out of a loop from
within a switch statement annoying, there are enough other patterns which
don't quite fit a language's looping structures that if a language
supports goto it would be the most logical approach. Consider, for
exampe, the scenario where a function needs to loop to find something and
then act upon the item; if the item isn't found, the function should quit.
While one could nest within the loop all the code that should execute when
the item is found, such placement would suggest that such code would expect
to be executed more than once. Having failure-exit logic following the
loop and a label beyond, and having the success case goto that label will
IMHO better fit the business logic than would burying the success code
within the loop or using some quirky "while(condition || ((error_flag=1),0)`
loop.
Some other languages allow loops to have an "else" clause, but
adding such a thing to C would break code since it would cause an "else"
that follows a loop to bind to that loop rather than an outer "if".
Something else that's broken then. Maybe C needs to be preserved just as
it is because the cracks to be papered over are just too wide!

Although if we're not too concerned with aesthetics, we can just use
'elsefor' or even '_Else'. It can't be that much more ungainly than
using 'default:' for switch, or other obviously bolted-on language
additions such as '_Bool' or '__attribute__'.
--
Bartc
Keith Thompson
2016-11-13 19:52:28 UTC
Permalink
Raw Message
Post by BartC
Post by Kaz Kylheku
Post by Keith Thompson
The idea is that the label is the name of the loop.
This is not significantly higher level than the concept that foo: <s>
makes foo the name of statement S.
(As we are all here aware, C requires a label to be followed by a
statement, and that effectively ties the label to the statement as its
name.)
Actually, a label can be followed by another label. Only the last needs
L1: L2: L3: ... <s>
Then S can have any number of different names. That's one difference
from a proposed loop-label.
The syntax of a labeled-statement (ignoring case and default labels) is:

identifier : statement

The statement can be any kind of statement, including another
labeled-statement.

If we add a labeled break whose target is an ordinary label (which would
be my second choice), we should require the statement following the
label to be either an iteration statement, a switch statement, or,
recursively, another labeled statement whose statement is an interation
or switch statement. (The standard should phrase that more clearly than
I just did.)

[...]
Post by BartC
(C labels, with their own namespace, can already have the same names as
variables, types, structs and enums in the same scope. Why anyone ever
thought that would be a good idea, I haven't got a clue. Fortunately I
guess not many know about it as you don't see it often!)
A label name can only appear in the label itself or in a goto
statement, so there's no ambiguity if the same name is used in
another context. You don't see it often because a well chosen name
for a label probably won't match a well chosen name for a variable.
The point isn't that anyone thought using the same name would be a
good idea. The point is that there was no good reason to forbid it.

The scoping rules for labels differ from those for any other
identifiers. All other identifiers are visible from their
declaration to the end of the enclosing scope. Labels are visible
throughout the enclosing function. I think it was just easier,
in terms of description and perhaps implementation, to put them
in separate namespaces. A single-pass compiler might have some
difficulty diagnosing some cases, such as a label conflicting with
an identifier in the same function that's no longer in scope.

I've never seen the fact that labels are in their own namespace
causing any problems. Have you?
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
BartC
2016-11-13 20:18:18 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by BartC
(C labels, with their own namespace, can already have the same names as
variables, types, structs and enums in the same scope. Why anyone ever
thought that would be a good idea, I haven't got a clue. Fortunately I
guess not many know about it as you don't see it often!)
I've never seen the fact that labels are in their own namespace
causing any problems. Have you?
Not usually, although gcc can give a good attempt at causing confusion:

void* L = &&L;

goto L;
goto *L;

L:;

Here both gotos jump to the same spot. But they can also be different
labels depending on how L - /the L declared as a void*/ - is defined.

(So even here it's starting to get tricky when I need to refer to a
specific L. A good thing I didn't confuse matters further by adding
braces, scopes and extra Ls!)

But, you don't seem bothered by this, yet you didn't like my
introduction of 'inner' and 'outer' which also dual but distinct roles.)
--
bartc
Keith Thompson
2016-11-13 20:55:42 UTC
Permalink
Raw Message
Post by BartC
Post by Keith Thompson
Post by BartC
(C labels, with their own namespace, can already have the same names as
variables, types, structs and enums in the same scope. Why anyone ever
thought that would be a good idea, I haven't got a clue. Fortunately I
guess not many know about it as you don't see it often!)
I've never seen the fact that labels are in their own namespace
causing any problems. Have you?
void* L = &&L;
goto L;
goto *L;
L:;
Here both gotos jump to the same spot. But they can also be different
labels depending on how L - /the L declared as a void*/ - is defined.
That's not gcc causing confusion. That's you causing confusion, using a
gcc-specific extension, by creating a contrived example.

What I meant by my question was, have you ever seen it cause any
problems *in real code*?
Post by BartC
(So even here it's starting to get tricky when I need to refer to a
specific L. A good thing I didn't confuse matters further by adding
braces, scopes and extra Ls!)
But, you don't seem bothered by this, yet you didn't like my
introduction of 'inner' and 'outer' which also dual but distinct roles.)
I'm not bothered by contrived examples that are intended to be
confusing. In real code, any decent programmer would use different
names for the label and for the pointer.

I didn't like your "inner" and "outer" proposal because it's more
complicated and less complete than what I've proposed (I addressed that
earlier).
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
BartC
2016-11-13 22:24:12 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by BartC
void* L = &&L;
goto L;
goto *L;
L:;
Here both gotos jump to the same spot. But they can also be different
labels depending on how L - /the L declared as a void*/ - is defined.
That's not gcc causing confusion. That's you causing confusion, using a
gcc-specific extension, by creating a contrived example.
You can use contrived examples (better called 'corner cases') to
investigate language features and possible ambiguities.

Here (in this gcc dialect), L (namespace 1) can be a label, and L
(namespace 2) can be part of an expression. A goto can be followed by a
label or an expression, so either of the two Ls can appear after the goto.

The way to distinguish them is that only a subset of expressions are
allowed after goto, and L (namespace 2) will need at least * or ( before
it and the goto.

So it's a tacky bit of design (and that includes a new use of && as a
unary op which gives an opporunity for an L (namespace 1) to appeat in
an expression too!)
Post by Keith Thompson
What I meant by my question was, have you ever seen it cause any
problems *in real code*?
You can always get around problems, that doesn't mean you can just
ignore potential issues.
Post by Keith Thompson
Post by BartC
But, you don't seem bothered by this, yet you didn't like my
introduction of 'inner' and 'outer' which also dual but distinct roles.)
I'm not bothered by contrived examples that are intended to be
confusing. In real code, any decent programmer would use different
names for the label and for the pointer.
(Exactly. So why go to the trouble of having a different namespace?)
Post by Keith Thompson
I didn't like your "inner" and "outer" proposal because it's more
complicated and less complete than what I've proposed (I addressed that
earlier).
(Complicated? I thought I'd take a ten-minute diversion to implement it
in one of my languages. But it turned out it already had it, and it
works fine! Although 'break outer' would be written as 'exit all' or
'exit 0'; normally it's 'exit' or 'exit 2' and so on.

But messing about with symbol tables, labels and namespaces /would/ be
more complicated.)
--
bartv
BartC
2016-11-13 11:25:24 UTC
Permalink
Raw Message
Post by s***@casperkitty.com
Post by Keith Thompson
Post by Kaz Kylheku
A break isn't a higher level feature relative to goto; it's a form of
goto with a few restrictions (which, as I illustrated, don't actually
have to exist in order to support the intended use).
It's the restrictions that make it a higher level feature.
Restrictions on the use of language functions are helpful when they allow
allow a compiler or a programmer to infer things that they could not readily
infer otherwise. Someone who sees that a "goto" is performed within a loop
and jumps to a point past the end of the loop could readily infer that the
goto is leaving the loop in question. I'm not sure what additional info the
described syntax could provide.
There are several patterns of label and goto that one could just as
'readily' infer correspond to if-statements or for-loops or while-loops.

But having actual if-statements or for-loops or while-loops makes things
more obvious and distinguishes the language from early Fortran or Basic.

Take this while-loop:

while (1) {
....
break;
....
}
puts("done");

You can infer, when you see the 'break' (and assuming it's not inside
'switch') that it will pass control to the next statement following the
loop body. You don't even to look at the end of the loop body.

And you can infer that control is passed to puts only from the preceding
loop. Now look at the version with goto:

while (1) {
....
goto L711;
....
}
L711:
puts("done");

Now, you have to search for L711 to see that it does actually quit the
loop like a break would. After someone else has edited the file, you
have to do it again to make sure. And control could pass to the puts by
any 'goto L711' in the function that you also have to eliminate.

In a complicated function the 'break' has a real advantage /because/ it
is restricted in how it works.

The thread is about the least painful way to tell the language, and the
user, that this break refers to the outer not inner while:

while (1) {
while (1) {
....
break;
....
}
}


(Some people might suggest using a smart editor to tell you that goto
L711 corresponds to exactly a break statement. That's great; we just
give up trying to make programming languages better and just offload the
effort to a smart editor! Where each editor does things differently.

My own editor is more 1980s style. However the language is from the
1970s so they're evenly matched!)
--
Bartc
Keith Thompson
2016-11-12 19:54:03 UTC
Permalink
Raw Message
Post by Richard Kettlewell
Post by Keith Thompson
We could fall back to using existing goto labels, where a label name can
be used in "break name" only if it labels a loop or switch statement.
Or we can invent a new syntax that's unambiguous.
:LABEL: do {
...
break LABEL;
} while (condition);
What’s the benefit of using a new label syntax? It seems like a
completely arbitrary extra bit of complexity.
Because it lets programmers use the new feature while not using gotos.

If I see a goto label in a piece of code, I have to search the entire
function definition to know how control could have gotten to that point.
I want a distinct syntax so I can use *structured* constructs without
mixing it up with gotos.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Richard Kettlewell
2016-11-12 20:09:41 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Richard Kettlewell
What’s the benefit of using a new label syntax? It seems like a
completely arbitrary extra bit of complexity.
Because it lets programmers use the new feature while not using gotos.
It’s not that hard to avoid typing the g-word.
Post by Keith Thompson
If I see a goto label in a piece of code, I have to search the entire
function definition to know how control could have gotten to that
point. I want a distinct syntax so I can use *structured* constructs
without mixing it up with gotos.
You could have a similar amount of searching to do to find a labelled
break/continue too, not that any of it should be remotely difficult if
you have tooling from any time in the last 2-3 decades. So I don’t see
a meaningful difference here.
--
http://www.greenend.org.uk/rjk/
Keith Thompson
2016-11-12 22:41:39 UTC
Permalink
Raw Message
Post by Richard Kettlewell
Post by Keith Thompson
Post by Richard Kettlewell
What’s the benefit of using a new label syntax? It seems like a
completely arbitrary extra bit of complexity.
Because it lets programmers use the new feature while not using gotos.
It’s not that hard to avoid typing the g-word.
Post by Keith Thompson
If I see a goto label in a piece of code, I have to search the entire
function definition to know how control could have gotten to that
point. I want a distinct syntax so I can use *structured* constructs
without mixing it up with gotos.
You could have a similar amount of searching to do to find a labelled
break/continue too, not that any of it should be remotely difficult if
you have tooling from any time in the last 2-3 decades. So I don’t see
a meaningful difference here.
That's fine. I've expressed my own preference; I'm not trying to change
yours.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Francis Glassborow
2016-11-13 13:23:20 UTC
Permalink
Raw Message
Post by Richard Kettlewell
Post by Keith Thompson
Post by Richard Kettlewell
What’s the benefit of using a new label syntax? It seems like a
completely arbitrary extra bit of complexity.
Because it lets programmers use the new feature while not using gotos.
It’s not that hard to avoid typing the g-word.
Post by Keith Thompson
If I see a goto label in a piece of code, I have to search the entire
function definition to know how control could have gotten to that
point. I want a distinct syntax so I can use *structured* constructs
without mixing it up with gotos.
You could have a similar amount of searching to do to find a labelled
break/continue too, not that any of it should be remotely difficult if
you have tooling from any time in the last 2-3 decades. So I don’t see
a meaningful difference here.
I see two differences

1) a named loop has the name before the break and so the reader does not
have to search forward and already knows that the break exits one or
more levels
2) If correctly designed the named loop construct cannot be the target
of a goto

Francis
Philipp Klaus Krause
2016-11-17 11:28:15 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Richard Kettlewell
Post by Keith Thompson
We could fall back to using existing goto labels, where a label name can
be used in "break name" only if it labels a loop or switch statement.
Or we can invent a new syntax that's unambiguous.
:LABEL: do {
...
break LABEL;
} while (condition);
What’s the benefit of using a new label syntax? It seems like a
completely arbitrary extra bit of complexity.
Because it lets programmers use the new feature while not using gotos.
If I see a goto label in a piece of code, I have to search the entire
function definition to know how control could have gotten to that point.
I want a distinct syntax so I can use *structured* constructs without
mixing it up with gotos.
And if the loop is big enough relative to the function definition, you
again have to look everywhere.
There are good arguments for not considering labeled break and continue
as "structured" (see e.g, "The Treewidth of Java Programs" by Jens
Gustedt et alii).

Philipp
Tim Rentsch
2016-11-12 16:40:54 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Thiago Adams
for loop1 ()
{
if ()
{
break loop1;
}
}
[...]
I like it. Currently an identifier can't appear after "for", "while",
or "do", so it won't break existing code. And it avoids using goto
labels.
Personally I think labelled breaks and/or continues are on the
wrong side of the cost/benefits line. I haven't done any
measurements, but a fair guess is that these things might be
found useful less than one loop in a thousand. It isn't worth
making the language more complicated for something that crops up
less than 0.1% of the time.

Having said that, if labelled breaks/continues were to be added
to C, I would advocate using regular statement labels, but
placing them on the controlled statements, eg

for(...) OUTER: {
...
while(...) INNER: {
...
if(...) continue OUTER;
}
...
}

This placement reinforces the idea that the loop labels are
"inside the scope" of the loop control. Also it works nicely
with do/while(), and if/elseif/else, if that is desired. As a
side benefit, a regular 'goto' with one of these labels restarts
the appropriate loop iteration, without going through any
incrementing or condition checks, which is sometimes useful (more
often I think than restarting the loop as a whole, which a label
on the outside would do).

Conversely, I would oppose any proposal that requires a syntax
extension. C already has statement labels - the only question
worth considering is where the needed labels should be placed.
BartC
2016-11-12 17:05:35 UTC
Permalink
Raw Message
Post by Tim Rentsch
if(...) continue OUTER;
Conversely, I would oppose any proposal that requires a syntax
extension.
'continue OUTER;' isn't a syntax extension?
--
Bartc
Tim Rentsch
2016-11-15 19:44:52 UTC
Permalink
Raw Message
Post by BartC
Post by Tim Rentsch
if(...) continue OUTER;
Conversely, I would oppose any proposal that requires a syntax
extension.
'continue OUTER;' isn't a syntax extension?
Everyone else understood what I meant. Are you really
so completely clueless? Or are you just practicing that
delightful deliberate obtuseness which has made you so
popular in comp.lang.c?
Keith Thompson
2016-11-15 20:14:51 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by BartC
Post by Tim Rentsch
if(...) continue OUTER;
Conversely, I would oppose any proposal that requires a syntax
extension.
'continue OUTER;' isn't a syntax extension?
Everyone else understood what I meant. Are you really
so completely clueless? Or are you just practicing that
delightful deliberate obtuseness which has made you so
popular in comp.lang.c?
Actually I thought BartC made a valid point. Clearly `continue
OUTER;` is a syntax extension. You obviously meant you don't want
a syntax extension other than allowing an identifier after break
or continue, but that's not quite what you wrote.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Tim Rentsch
2016-11-22 11:14:29 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Tim Rentsch
Post by BartC
Post by Tim Rentsch
if(...) continue OUTER;
Conversely, I would oppose any proposal that requires a syntax
extension.
'continue OUTER;' isn't a syntax extension?
Everyone else understood what I meant. Are you really
so completely clueless? Or are you just practicing that
delightful deliberate obtuseness which has made you so
popular in comp.lang.c?
Actually I thought BartC made a valid point.
I might agree with you _if_ I thought anyone was confused about
what I meant or if I thought Bart was trying to clear up some
potential confusion. But I don't think anyone was confused about
what I meant - surely it's obvious from context (sneakily snipped
by Bart) that I was talking just about labels - nor do I think
Bart was trying to clear up any confusion - his followup posting
shows his intention was anything but.
Post by Keith Thompson
Clearly `continue
OUTER;` is a syntax extension. You obviously meant you don't want
a syntax extension other than allowing an identifier after break
or continue, but that's not quite what you wrote.
Something like this is what someone would say if their interest
lay in advancing the conversation. Clearly that is not Bart's
interest, which is just stirring up trouble - and as long as he
continues to act like someone who simply enjoys being an asshole,
he may expect to get called on it.

I note by the way that you responded to the same posting of mine
that Bart did, including a reponse to the paragraph that had the
"I would oppose any proposal that requires a syntax extension,"
sentence in it. Yet you apparently didn't feel any need to point
out the syntax extension aspect of, eg, 'continue OUTER;'. That
says to me that no one had any problem understanding what was
meant, and it was more of an effort to misunderstand than it was
to understand what was intended.
BartC
2016-11-22 13:59:38 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by Keith Thompson
Post by BartC
'continue OUTER;' isn't a syntax extension?
Actually I thought BartC made a valid point.
I might agree with you _if_ I thought anyone was confused about
what I meant or if I thought Bart was trying to clear up some
potential confusion. But I don't think anyone was confused about
what I meant - surely it's obvious from context (sneakily snipped
by Bart) that I was talking just about labels - nor do I think
Bart was trying to clear up any confusion - his followup posting
shows his intention was anything but.
I didn't make a follow-up post.
Post by Tim Rentsch
Post by Keith Thompson
Clearly `continue
OUTER;` is a syntax extension. You obviously meant you don't want
a syntax extension other than allowing an identifier after break
or continue, but that's not quite what you wrote.
Something like this is what someone would say if their interest
lay in advancing the conversation.
Clearly that is not Bart's
interest, which is just stirring up trouble - and as long as he
continues to act like someone who simply enjoys being an asshole,
he may expect to get called on it.
That comment is out of order.
Post by Tim Rentsch
I note by the way that you responded to the same posting of mine
that Bart did, including a reponse to the paragraph that had the
"I would oppose any proposal that requires a syntax extension,"
sentence in it. Yet you apparently didn't feel any need to point
out the syntax extension aspect of, eg, 'continue OUTER;'. That
says to me that no one had any problem understanding what was
meant, and it was more of an effort to misunderstand than it was
to understand what was intended.
I don't believe you understand what a syntax extension is.

A syntax extension would involve changing the language grammar, and
updating every C compiler on the planet.

You don't get a free pass for 'continue OUTER' just because it suits you
or because you think it's a such a minor change that it doesn't count!

So, if you are going to go to that trouble to make even a small
extension to the syntax of C, then more solutions involving syntax might
as well be considered.
--
Bartc
Tim Rentsch
2016-12-10 07:26:12 UTC
Permalink
Raw Message
Post by BartC
[...]
Post by Tim Rentsch
I note by the way that you responded to the same posting of mine
that Bart did, including a reponse to the paragraph that had the
"I would oppose any proposal that requires a syntax extension,"
sentence in it. Yet you apparently didn't feel any need to point
out the syntax extension aspect of, eg, 'continue OUTER;'. That
says to me that no one had any problem understanding what was
meant, and it was more of an effort to misunderstand than it was
to understand what was intended.
I don't believe you understand what a syntax extension is.
A syntax extension would involve changing the language grammar, and
updating every C compiler on the planet.
You don't get a free pass for 'continue OUTER' just because it suits
you or because you think it's a such a minor change that it doesn't
count!
So, if you are going to go to that trouble to make even a small
extension to the syntax of C, then more solutions involving syntax
might as well be considered.
Your capacity to willfully misunderstand is truly astonishing.
BartC
2016-12-10 19:34:09 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by BartC
[...]
Post by Tim Rentsch
I note by the way that you responded to the same posting of mine
that Bart did, including a reponse to the paragraph that had the
"I would oppose any proposal that requires a syntax extension,"
sentence in it. Yet you apparently didn't feel any need to point
out the syntax extension aspect of, eg, 'continue OUTER;'. That
says to me that no one had any problem understanding what was
meant, and it was more of an effort to misunderstand than it was
to understand what was intended.
I don't believe you understand what a syntax extension is.
A syntax extension would involve changing the language grammar, and
updating every C compiler on the planet.
You don't get a free pass for 'continue OUTER' just because it suits
you or because you think it's a such a minor change that it doesn't
count!
So, if you are going to go to that trouble to make even a small
extension to the syntax of C, then more solutions involving syntax
might as well be considered.
Your capacity to willfully misunderstand is truly astonishing.
Nowhere near as bad as yours.

I tried your 'continue OUTER' proposal, with an OUTER label on a
surrounding loop, with a number of C compilers, and it didn't work.

Is there any way of making it work without changing the syntax? If not
then it's a syntax extension.
Tim Rentsch
2016-12-25 18:02:45 UTC
Permalink
Raw Message
Merry Christmas...

Keith Thompson
2016-11-12 19:57:06 UTC
Permalink
Raw Message
Tim Rentsch <***@alumni.caltech.edu> writes:
[...]
Post by Tim Rentsch
Personally I think labelled breaks and/or continues are on the
wrong side of the cost/benefits line. I haven't done any
measurements, but a fair guess is that these things might be
found useful less than one loop in a thousand. It isn't worth
making the language more complicated for something that crops up
less than 0.1% of the time.
Fair enough -- but I've used this feature in languages that support it,
and found it useful.
Post by Tim Rentsch
Having said that, if labelled breaks/continues were to be added
to C, I would advocate using regular statement labels, but
placing them on the controlled statements, eg
for(...) OUTER: {
...
while(...) INNER: {
...
if(...) continue OUTER;
}
...
}
This placement reinforces the idea that the loop labels are
"inside the scope" of the loop control.
I disagree. That placement tends to hide the name, which I would like
to think of as the name of the loop as a whole, not of the controlled
statement.
Post by Tim Rentsch
Also it works nicely
with do/while(), and if/elseif/else, if that is desired. As a
side benefit, a regular 'goto' with one of these labels restarts
the appropriate loop iteration, without going through any
incrementing or condition checks, which is sometimes useful (more
often I think than restarting the loop as a whole, which a label
on the outside would do).
I don't see that as a benefit.
Post by Tim Rentsch
Conversely, I would oppose any proposal that requires a syntax
extension. C already has statement labels - the only question
worth considering is where the needed labels should be placed.
I doubt that any proposal to add multi-level breaks is going to be
approved anyway.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Thiago Adams
2016-11-12 21:16:13 UTC
Permalink
Raw Message
[...]
Post by Tim Rentsch
Personally I think labelled breaks and/or continues are on the
wrong side of the cost/benefits line. I haven't done any
measurements, but a fair guess is that these things might be
found useful less than one loop in a thousand. It isn't worth
making the language more complicated for something that crops up
less than 0.1% of the time.
I agree that is something not used.
This is because inner loops are written as other function representing smaller algorithms. The out state generally enters as function arguments and one break does the job. This pattern is recursive.

for ()
{
//inner
if (InnerAlgoritm(outstate..))
{
break;
}
}
BartC
2016-11-12 22:10:59 UTC
Permalink
Raw Message
Post by Thiago Adams
[...]
Post by Tim Rentsch
Personally I think labelled breaks and/or continues are on the
wrong side of the cost/benefits line. I haven't done any
measurements, but a fair guess is that these things might be
found useful less than one loop in a thousand. It isn't worth
making the language more complicated for something that crops up
less than 0.1% of the time.
I agree that is something not used.
This is because inner loops are written as other function representing smaller algorithms. The out state generally enters as function arguments and one break does the job. This pattern is recursive.
for ()
{
//inner
if (InnerAlgoritm(outstate..))
{
break;
}
}
That's just evading the issue.

Decomposing into functions instead of using nested loops might be one
reason why it's not needed so much. But that's not the same: a return
inside a loop in a function will not also break out of the outer loop in
the caller.

Your example needs to set and check another separate status before it
will exit the outer loop too.

Looking at my own code, breaking out of two loops is quite rare, but I'm
glad that when I have to do it (when not writing C), I can just do it
without having to decompose into functions, or add flags and extra
logic, or have to use gotos.

What /does/ need to be addressed in C however is not being able to break
out of even one loop if the code involved is inside a switch statement.
That's just silly.
--
Bartc
Philipp Klaus Krause
2016-11-17 11:33:38 UTC
Permalink
Raw Message
Post by BartC
[…]
Looking at my own code, breaking out of two loops is quite rare, but I'm
glad that when I have to do it (when not writing C), I can just do it
without having to decompose into functions, or add flags and extra
logic, or have to use gotos.
What /does/ need to be addressed in C however is not being able to break
out of even one loop if the code involved is inside a switch statement.
That's just silly.
Both uses cases are adequately covered by goto. Ans multilevel break and
continue can make control flow just as comploicated as goto.

Philipp
BartC
2016-11-17 12:15:57 UTC
Permalink
Raw Message
Post by Philipp Klaus Krause
Post by BartC
[…]
Looking at my own code, breaking out of two loops is quite rare, but I'm
glad that when I have to do it (when not writing C), I can just do it
without having to decompose into functions, or add flags and extra
logic, or have to use gotos.
What /does/ need to be addressed in C however is not being able to break
out of even one loop if the code involved is inside a switch statement.
That's just silly.
Both uses cases are adequately covered by goto. Ans multilevel break and
continue can make control flow just as comploicated as goto.
I guess you've never seen, or have forgotten, what 1970s-style Fortran
or Basic looked like.
--
Bartc
Tim Rentsch
2016-11-15 19:42:39 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Tim Rentsch
Personally I think labelled breaks and/or continues are on the
wrong side of the cost/benefits line. I haven't done any
measurements, but a fair guess is that these things might be
found useful less than one loop in a thousand. It isn't worth
making the language more complicated for something that crops up
less than 0.1% of the time.
Fair enough -- but I've used this feature in languages that support it,
and found it useful.
Post by Tim Rentsch
Having said that, if labelled breaks/continues were to be added
to C, I would advocate using regular statement labels, but
placing them on the controlled statements, eg
for(...) OUTER: {
...
while(...) INNER: {
...
if(...) continue OUTER;
}
...
}
This placement reinforces the idea that the loop labels are
"inside the scope" of the loop control.
I disagree.
I'm not sure what it is you think you're disagreeing with. The
only assertion I've made is that this placement reinforces the
idea that the loop labels are "inside the scope" of the loop
control. Do you disagree with that assertion? It seems fairly
uncontroversial.
Post by Keith Thompson
That placement tends to hide the name, which I would like to
think of as the name of the loop as a whole, not of the
controlled statement.
If the label is put outside rather than inside, it looks like
it might be the target of a regular goto. Conversely, it
would be very unusual to see a label on "the inside" of an
if(), for(), while(), etc. That distinction could be used
by compilers to provide useful warning messages.

By the way, personally I don't think that much hiding is going on
here. I agree the name stands out less than a name put, eg, at
the beginning of a line. In my view though that is an advantage
as well as a potential disadvantage.
Post by Keith Thompson
Post by Tim Rentsch
Also it works nicely
with do/while(), and if/elseif/else, if that is desired. As a
side benefit, a regular 'goto' with one of these labels restarts
the appropriate loop iteration, without going through any
incrementing or condition checks, which is sometimes useful (more
often I think than restarting the loop as a whole, which a label
on the outside would do).
I don't see that as a benefit.
What I think you mean is being able to do this may offer a benefit
but you don't assign much weight to that (and perhaps even zero
or negative weight).
Post by Keith Thompson
Post by Tim Rentsch
Conversely, I would oppose any proposal that requires a syntax
extension. C already has statement labels - the only question
worth considering is where the needed labels should be placed.
I doubt that any proposal to add multi-level breaks is going to be
approved anyway.
Check. I'm just trying to stimulate some discussion and
get people thinking a bit more deeply about what the
different tradeoffs might be.
Keith Thompson
2016-11-15 20:20:43 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by Keith Thompson
[...]
Post by Tim Rentsch
Personally I think labelled breaks and/or continues are on the
wrong side of the cost/benefits line. I haven't done any
measurements, but a fair guess is that these things might be
found useful less than one loop in a thousand. It isn't worth
making the language more complicated for something that crops up
less than 0.1% of the time.
Fair enough -- but I've used this feature in languages that support it,
and found it useful.
Post by Tim Rentsch
Having said that, if labelled breaks/continues were to be added
to C, I would advocate using regular statement labels, but
placing them on the controlled statements, eg
for(...) OUTER: {
...
while(...) INNER: {
...
if(...) continue OUTER;
}
...
}
This placement reinforces the idea that the loop labels are
"inside the scope" of the loop control.
I disagree.
I'm not sure what it is you think you're disagreeing with. The
only assertion I've made is that this placement reinforces the
idea that the loop labels are "inside the scope" of the loop
control. Do you disagree with that assertion? It seems fairly
uncontroversial.
I do not share your preference for what you're advocating. I think it's
clearer if the label applies to the loop as a whole rather than to the
statement that it controls.
Post by Tim Rentsch
Post by Keith Thompson
That placement tends to hide the name, which I would like to
think of as the name of the loop as a whole, not of the
controlled statement.
If the label is put outside rather than inside, it looks like
it might be the target of a regular goto. Conversely, it
would be very unusual to see a label on "the inside" of an
if(), for(), while(), etc. That distinction could be used
by compilers to provide useful warning messages.
It could be the target of a regular goto either way, unless a new
restriction is added (which I would oppose).
Post by Tim Rentsch
By the way, personally I don't think that much hiding is going on
here. I agree the name stands out less than a name put, eg, at
the beginning of a line. In my view though that is an advantage
as well as a potential disadvantage.
Post by Keith Thompson
Post by Tim Rentsch
Also it works nicely
with do/while(), and if/elseif/else, if that is desired. As a
side benefit, a regular 'goto' with one of these labels restarts
the appropriate loop iteration, without going through any
incrementing or condition checks, which is sometimes useful (more
often I think than restarting the loop as a whole, which a label
on the outside would do).
I don't see that as a benefit.
What I think you mean is being able to do this may offer a benefit
but you don't assign much weight to that (and perhaps even zero
or negative weight).
What I mean is that I don't see that as a benefit. Adding a label to a
statement adds the capability of targeting that statement with a goto.
Unless I actually want to use a goto, I don't see that as a benefit;
rather, I see it as harmful because I have to verify that there are no
goto statements within the enclosing function before I can be sure of
how control can reach that statement. (Which is why I'd rather see a
distinct syntax for loop names, rather than reusing the existing label
syntax.)
Post by Tim Rentsch
Post by Keith Thompson
Post by Tim Rentsch
Conversely, I would oppose any proposal that requires a syntax
extension. C already has statement labels - the only question
worth considering is where the needed labels should be placed.
I doubt that any proposal to add multi-level breaks is going to be
approved anyway.
Check. I'm just trying to stimulate some discussion and
get people thinking a bit more deeply about what the
different tradeoffs might be.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Tim Rentsch
2016-11-22 11:28:20 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Tim Rentsch
Post by Keith Thompson
[...]
Post by Tim Rentsch
Personally I think labelled breaks and/or continues are on the
wrong side of the cost/benefits line. I haven't done any
measurements, but a fair guess is that these things might be
found useful less than one loop in a thousand. It isn't worth
making the language more complicated for something that crops up
less than 0.1% of the time.
Fair enough -- but I've used this feature in languages that support it,
and found it useful.
Post by Tim Rentsch
Having said that, if labelled breaks/continues were to be added
to C, I would advocate using regular statement labels, but
placing them on the controlled statements, eg
for(...) OUTER: {
...
while(...) INNER: {
...
if(...) continue OUTER;
}
...
}
This placement reinforces the idea that the loop labels are
"inside the scope" of the loop control.
I disagree.
I'm not sure what it is you think you're disagreeing with. The
only assertion I've made is that this placement reinforces the
idea that the loop labels are "inside the scope" of the loop
control. Do you disagree with that assertion? It seems fairly
uncontroversial.
I do not share your preference for what you're advocating. I think it's
clearer if the label applies to the loop as a whole rather than to the
statement that it controls.
I'm not sure what you mean by the second sentence there. Surely
if one knows what rule is in effect it is equally clear either
way. Do you mean that having the label on the outside is what
you're more used to? Or something else?
Post by Keith Thompson
Post by Tim Rentsch
Post by Keith Thompson
That placement tends to hide the name, which I would like to
think of as the name of the loop as a whole, not of the
controlled statement.
If the label is put outside rather than inside, it looks like
it might be the target of a regular goto. Conversely, it
would be very unusual to see a label on "the inside" of an
if(), for(), while(), etc. That distinction could be used
by compilers to provide useful warning messages.
It could be the target of a regular goto either way, unless a new
restriction is added (which I would oppose).
Yes, it could be, but that would be less likely if the label were
on the controlled statement. To say that another way, if I see a
label on outside (eg, before a 'while()'), my uncertainty (ie,
about whether the label is there to be a 'goto' target) is higher
than if the label is on the controlled statement.
Post by Keith Thompson
Post by Tim Rentsch
By the way, personally I don't think that much hiding is going on
here. I agree the name stands out less than a name put, eg, at
the beginning of a line. In my view though that is an advantage
as well as a potential disadvantage.
Post by Keith Thompson
Post by Tim Rentsch
Also it works nicely
with do/while(), and if/elseif/else, if that is desired. As a
side benefit, a regular 'goto' with one of these labels restarts
the appropriate loop iteration, without going through any
incrementing or condition checks, which is sometimes useful (more
often I think than restarting the loop as a whole, which a label
on the outside would do).
I don't see that as a benefit.
What I think you mean is being able to do this may offer a benefit
but you don't assign much weight to that (and perhaps even zero
or negative weight).
What I mean is that I don't see that as a benefit. Adding a label to a
statement adds the capability of targeting that statement with a goto.
Unless I actually want to use a goto, I don't see that as a benefit;
rather, I see it as harmful because I have to verify that there are no
goto statements within the enclosing function before I can be sure of
how control can reach that statement. (Which is why I'd rather see a
distinct syntax for loop names, rather than reusing the existing label
syntax.)
I think we mean the same thing but are using different words to
express it. In any case I'm pretty sure I understand your
position.
Keith Thompson
2016-11-22 16:32:12 UTC
Permalink
Raw Message
[...]
Post by Tim Rentsch
Post by Keith Thompson
I do not share your preference for what you're advocating. I think it's
clearer if the label applies to the loop as a whole rather than to the
statement that it controls.
I'm not sure what you mean by the second sentence there. Surely
if one knows what rule is in effect it is equally clear either
way. Do you mean that having the label on the outside is what
you're more used to? Or something else?
I mean that I find having the label apply to the loop statement (i.e.,
having a labeled-statement of the form
identifier : iteration-statement
clearer than having the label apply to the substatement:
while (expr) identifier : statement

It's true that it's what I'm more used to, but that wasn't my main
point. I said and meant that I find the first form clearer.

[...]
Post by Tim Rentsch
Post by Keith Thompson
It could be the target of a regular goto either way, unless a new
restriction is added (which I would oppose).
Yes, it could be, but that would be less likely if the label were
on the controlled statement. To say that another way, if I see a
label on outside (eg, before a 'while()'), my uncertainty (ie,
about whether the label is there to be a 'goto' target) is higher
than if the label is on the controlled statement.
And yet someone could still write a goto targeting any label wherever
it is.

[...]
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Tim Rentsch
2016-11-23 16:40:44 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Tim Rentsch
Post by Keith Thompson
I do not share your preference for what you're advocating. I think it's
clearer if the label applies to the loop as a whole rather than to the
statement that it controls.
I'm not sure what you mean by the second sentence there. Surely
if one knows what rule is in effect it is equally clear either
way. Do you mean that having the label on the outside is what
you're more used to? Or something else?
I mean that I find having the label apply to the loop statement (i.e.,
having a labeled-statement of the form
identifier : iteration-statement
while (expr) identifier : statement
It's true that it's what I'm more used to, but that wasn't my main
point. I said and meant that I find the first form clearer.
[...]
This response doesn't tell me anything because the word that is
stumping me is "clearer". Looking up "clear" in several online
dictionaries, all the definitions seem to apply equally to the
two cases. Can you say what you mean without using the word
"clear" (and hopefully without simply substituting a different
abstract term, eg, "simple")?
Post by Keith Thompson
Post by Tim Rentsch
Post by Keith Thompson
It could be the target of a regular goto either way, unless a new
restriction is added (which I would oppose).
Yes, it could be, but that would be less likely if the label were
on the controlled statement. To say that another way, if I see a
label on outside (eg, before a 'while()'), my uncertainty (ie,
about whether the label is there to be a 'goto' target) is higher
than if the label is on the controlled statement.
And yet someone could still write a goto targeting any label wherever
it is.
We seem to be going around in circles. Your response looks like
it is simply restating what you said before. Do you think I
didn't understand you the first time? Or is there some new
content here that I overlooked? If all you are doing is saying
again what you said before I don't know what you're trying to
accomplish. Did you not understand the point of my comment?
Keith Thompson
2016-11-23 19:34:21 UTC
Permalink
Raw Message
Post by Tim Rentsch
Post by Keith Thompson
[...]
Post by Tim Rentsch
Post by Keith Thompson
I do not share your preference for what you're advocating. I think it's
clearer if the label applies to the loop as a whole rather than to the
statement that it controls.
I'm not sure what you mean by the second sentence there. Surely
if one knows what rule is in effect it is equally clear either
way. Do you mean that having the label on the outside is what
you're more used to? Or something else?
I mean that I find having the label apply to the loop statement (i.e.,
having a labeled-statement of the form
identifier : iteration-statement
while (expr) identifier : statement
It's true that it's what I'm more used to, but that wasn't my main
point. I said and meant that I find the first form clearer.
[...]
Post by Tim Rentsch
We seem to be going around in circles. Your response looks like
it is simply restating what you said before. Do you think I
didn't understand you the first time?
I do, because you said so ("I'm not sure what you mean by the second
sentence there.")
Post by Tim Rentsch
Or is there some new
content here that I overlooked? If all you are doing is saying
again what you said before I don't know what you're trying to
accomplish. Did you not understand the point of my comment?
I suppose I didn't understand the point of your comment, and I don't
understand why you're not sure what I meant above.

I don't see why putting the label on the substatement:
while (1) LABEL: {
...
break LABEL;
...
}
is better than putting it on the iteration statement itself:
LABEL: while (1) {
...
break LABEL;
...
}

Given at least one very common brace layout, it tends to hide the
label in the middle of a line. (Styles that put the opening brace
at the beginning of a line wouldn't have that issue.) And at the
risk of repeating myself, I think of a break (rather loosely) as
an operation that applies to the loop as a whole. In the example
above, it logically applies to the while statement, not to the
compound statement. Putting the label on the iteration statement
is consistent with similar constructs in other languages; putting
it on the substatement would be, as far as I know, unique.

Is the only purpose of labeling the substatement the fact that
it makes it a less obvious target for a goto? If so, I find that
argument frankly trivial, and outweighed by the advantages (in my
opinion) of labeling the iteration statement.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Tim Rentsch
2016-12-01 20:15:39 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by Tim Rentsch
Post by Keith Thompson
[...]
Post by Tim Rentsch
Post by Keith Thompson
I do not share your preference for what you're advocating. I think it's
clearer if the label applies to the loop as a whole rather than to the
statement that it controls.
I'm not sure what you mean by the second sentence there. Surely
if one knows what rule is in effect it is equally clear either
way. Do you mean that having the label on the outside is what
you're more used to? Or something else?
I mean that I find having the label apply to the loop statement (i.e.,
having a labeled-statement of the form
identifier : iteration-statement
while (expr) identifier : statement
It's true that it's what I'm more used to, but that wasn't my main
point. I said and meant that I find the first form clearer.
[...]
Post by Tim Rentsch
We seem to be going around in circles. Your response looks like
it is simply restating what you said before. Do you think I
didn't understand you the first time?
I do, because you said so ("I'm not sure what you mean by the second
sentence there.")
You left out the intervening context. I don't know why you
did that, since it totally changes the sense of what I was
saying. Here is that context again:

|= >>> It's true that it's what I'm more used to, but that wasn't my main
|= >>> point. I said and meant that I find the first form clearer.
|= >>>
|= >>> [...]
|= >>
|= >> This response doesn't tell me anything because the word that is
|= >> stumping me is "clearer". Looking up "clear" in several online
|= >> dictionaries, all the definitions seem to apply equally to the
|= >> two cases. Can you say what you mean without using the word
|= >> "clear" (and hopefully without simply substituting a different
|= >> abstract term, eg, "simple")?
|= >>
|= >>>>> It could be the target of a regular goto either way, unless a new
|= >>>>> restriction is added (which I would oppose).
|= >>>>
|= >>>> Yes, it could be, but that would be less likely if the label were
|= >>>> on the controlled statement. To say that another way, if I see a
|= >>>> label on outside (eg, before a 'while()'), my uncertainty (ie,
|= >>>> about whether the label is there to be a 'goto' target) is higher
|= >>>> than if the label is on the controlled statement.
|= >>>
|= >>> And yet someone could still write a goto targeting any label wherever
|= >>> it is.
|= >>
|= >> We seem to be going around in circles. Your response looks like
|= >> it is simply restating what you said before. Do you think I
|= >> didn't understand you the first time?

What I understood was your statement that "someone could still
write a goto targeting any label wherever it is." It seems like
you are just repeating what you said before.

It the part before, where you said "I said and meant that I find
the first form clearer" that I didn't understand. I explained
what I didn't undestand about it - that I don't know what you
mean by "clearer" - and asked a question: Can you say what you
mean without using the word "clear" (or clearer, etc)? I still
would like an answer to that question, if you have one.
Post by Keith Thompson
Post by Tim Rentsch
Or is there some new
content here that I overlooked? If all you are doing is saying
again what you said before I don't know what you're trying to
accomplish. Did you not understand the point of my comment?
I suppose I didn't understand the point of your comment, and I don't
understand why you're not sure what I meant above.
while (1) LABEL: {
...
break LABEL;
...
}
LABEL: while (1) {
...
break LABEL;
...
}
Given at least one very common brace layout, it tends to hide the
label in the middle of a line.
Yes, it does. I don't see that as a negative. In a way it's a
positive, since it serves a different purpose than a label meant
as the target of a goto, and connotes a different scoping. Of
course the actual scope rules are the same, but presumably such
labels are meant to be referenced only inside the body of the
associated for(), while(), etc.
Post by Keith Thompson
And at the
risk of repeating myself, I think of a break (rather loosely) as
an operation that applies to the loop as a whole. In the example
above, it logically applies to the while statement, not to the
compound statement.
I think I mostly understand what you're saying here. I think of
'break' and 'continue' a little bit differently.
Post by Keith Thompson
Putting the label on the iteration statement
is consistent with similar constructs in other languages; putting
it on the substatement would be, as far as I know, unique.
I acknowledge that. I don't always think something is convenient
just because it is conventional.
Post by Keith Thompson
Is the only purpose of labeling the substatement the fact that
it makes it a less obvious target for a goto?
I would say several things (none having the word obvious in
them):

such a label is less likely to be a goto target;
placing a label on the controlled statement more accurately
reflects the intended scope of where the label may be used;
it allows distinction between actions related to the body and
actions related to the statement as a whole (in for(), for
example, initialization is not part of 'continue').
Post by Keith Thompson
If so, I find that argument frankly trivial,
My comments are not arguments, just statements.
Post by Keith Thompson
and outweighed by the advantages (in my
opinion) of labeling the iteration statement.
I don't know what you think those advantages are besides that
it's how you are used to thinking of things. AFAIK you haven't
articulated any other than that.
Keith Thompson
2016-12-01 21:02:45 UTC
Permalink
Raw Message
Tim Rentsch <***@alumni.caltech.edu> writes:
[BIG SNIP]
Post by Tim Rentsch
What I understood was your statement that "someone could still
write a goto targeting any label wherever it is." It seems like
you are just repeating what you said before.
It the part before, where you said "I said and meant that I find
the first form clearer" that I didn't understand. I explained
what I didn't undestand about it - that I don't know what you
mean by "clearer" - and asked a question: Can you say what you
mean without using the word "clear" (or clearer, etc)? I still
would like an answer to that question, if you have one.
I don't think there's much I can add without repeating myself.

To summarize what I've written previously, I'd prefer to have
something that follows existing practice from other languages,
which in my experience works quite well. I'd prefer, if practical,
to use a different syntax for loop names than for label names,
though I'm not sure what syntax would be appropriate (I like Ada's
approach, but that's not an option for C because Ada loop names use
the same syntax as C goto labels). I'd prefer to have the label
name clearly visible, not hidden in the middle of a line.

[...]
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Tim Rentsch
2016-12-10 07:20:20 UTC
Permalink
Raw Message
Post by Keith Thompson
[BIG SNIP]
Post by Tim Rentsch
What I understood was your statement that "someone could still
write a goto targeting any label wherever it is." It seems like
you are just repeating what you said before.
It the part before, where you said "I said and meant that I find
the first form clearer" that I didn't understand. I explained
what I didn't undestand about it - that I don't know what you
mean by "clearer" - and asked a question: Can you say what you
mean without using the word "clear" (or clearer, etc)? I still
would like an answer to that question, if you have one.
I don't think there's much I can add without repeating myself.
To summarize what I've written previously, I'd prefer to have
something that follows existing practice from other languages,
which in my experience works quite well. I'd prefer, if practical,
to use a different syntax for loop names than for label names,
though I'm not sure what syntax would be appropriate (I like Ada's
approach, but that's not an option for C because Ada loop names use
the same syntax as C goto labels). I'd prefer to have the label
name clearly visible, not hidden in the middle of a line.
ISTM that all you're doing here is stating some personal
preferences. However I believe I understand what your
stated preferences are, so if you want we can just leave it
there.
luserdroog
2016-11-17 15:19:07 UTC
Permalink
Raw Message
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
machine should break or continue /to/.
The argument could be a looping keyword (for, while, do) or
'switch'. For a switch in a for-loop, you can now write
`break switch;` to stay in the loop or `break for;` to get
out of it.
If a switch or loop is immediately preceeded by a 'label:',
then that label may also serve to designate /which loop/
in a nested set of loops.
Thanks for all responses. Special thanks to Kaz for
correctly extrapolating a more well-argued explanation
of what I was suggesting. But a bizarre turn occurred
as I started to read the back-and-forth between Keith
and Bart -- viz. I started to agree with Bart.

How to prevent nonsensical or unnecessarily confusing
constructs?

And then Tim's message appears to show the way out.
It does make a lot more sense to put the label on
the controlled statement. This makes `goto label;`
clear and usable.

But if you've gone that far, it's not such a chore
to add a label to the part of the loop you need to
get to.

while (cond) {
switch (thing) {
default: goto continue_cond;
}
continue_cond: ;
}

This way has the tremendous advantage of already
being implemented.
Keith Thompson
2016-11-17 16:47:46 UTC
Permalink
Raw Message
Post by luserdroog
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
machine should break or continue /to/.
The argument could be a looping keyword (for, while, do) or
'switch'. For a switch in a for-loop, you can now write
`break switch;` to stay in the loop or `break for;` to get
out of it.
If a switch or loop is immediately preceeded by a 'label:',
then that label may also serve to designate /which loop/
in a nested set of loops.
Thanks for all responses. Special thanks to Kaz for
correctly extrapolating a more well-argued explanation
of what I was suggesting. But a bizarre turn occurred
as I started to read the back-and-forth between Keith
and Bart -- viz. I started to agree with Bart.
How to prevent nonsensical or unnecessarily confusing
constructs?
And then Tim's message appears to show the way out.
It does make a lot more sense to put the label on
the controlled statement. This makes `goto label;`
clear and usable.
But if you've gone that far, it's not such a chore
to add a label to the part of the loop you need to
get to.
while (cond) {
switch (thing) {
default: goto continue_cond;
}
continue_cond: ;
}
This way has the tremendous advantage of already
being implemented.
Yes, of *course* you can do any kind of multi-level break or continue
using gotos. You can do single-level break or continue using gotos, and
if the language didn't have break and continue you'd have to.

Currently, you can use break or continue for a single level, but you
have to resort to goto for two or more levels. I'd like to use break or
continue for any number of levels, and there's ample precedent for such
a feature in other languages.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Francis Glassborow
2016-11-17 17:18:39 UTC
Permalink
Raw Message
Post by Keith Thompson
Post by luserdroog
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
machine should break or continue /to/.
The argument could be a looping keyword (for, while, do) or
'switch'. For a switch in a for-loop, you can now write
`break switch;` to stay in the loop or `break for;` to get
out of it.
If a switch or loop is immediately preceeded by a 'label:',
then that label may also serve to designate /which loop/
in a nested set of loops.
Thanks for all responses. Special thanks to Kaz for
correctly extrapolating a more well-argued explanation
of what I was suggesting. But a bizarre turn occurred
as I started to read the back-and-forth between Keith
and Bart -- viz. I started to agree with Bart.
How to prevent nonsensical or unnecessarily confusing
constructs?
And then Tim's message appears to show the way out.
It does make a lot more sense to put the label on
the controlled statement. This makes `goto label;`
clear and usable.
But if you've gone that far, it's not such a chore
to add a label to the part of the loop you need to
get to.
while (cond) {
switch (thing) {
default: goto continue_cond;
}
continue_cond: ;
}
This way has the tremendous advantage of already
being implemented.
Yes, of *course* you can do any kind of multi-level break or continue
using gotos. You can do single-level break or continue using gotos, and
if the language didn't have break and continue you'd have to.
Currently, you can use break or continue for a single level, but you
have to resort to goto for two or more levels. I'd like to use break or
continue for any number of levels, and there's ample precedent for such
a feature in other languages.
OK, could be useful but I actually want to avoid a syntax that can use
the structure label as a destination for a goto which is why I prefer
the suggestion to label the controlled statement.

Francis
Keith Thompson
2016-11-17 17:39:55 UTC
Permalink
Raw Message
[...]
Post by Francis Glassborow
Post by Keith Thompson
Currently, you can use break or continue for a single level, but you
have to resort to goto for two or more levels. I'd like to use break or
continue for any number of levels, and there's ample precedent for such
a feature in other languages.
OK, could be useful but I actually want to avoid a syntax that can use
the structure label as a destination for a goto which is why I prefer
the suggestion to label the controlled statement.
How does that prevent using it as the target of a goto?

This:

while (1) LABEL: {
// ...
}
// ...
goto LABEL;

is already perfectly legal. You probably wouldn't *want* to do that,
but if I'm reading the code I still have to verify that there isn't a
`goto LABEL;` somewhere in the function.

A new syntax that provides a name for a loop or switch statement,
such as:

:LOOP_NAME: while (1) {
// ...
}

would permit the use of LOOP_NAME in a break or continue, but not in a
goto.

There is precedent in Perl (and probably other languages) for using a
goto label as a loop name:

LABEL: while (1) {
# ...
last LABEL; # like C's break
next LABEL; # like C's continue
}
goto LABEL; # legal

And in my experience, the fact that the label *could* be the target of a
goto hasn't been much of a problem (probably because in Perl I mostly
work on my own code and I can be reasonly sure I haven't used a goto).

There is precedent in Ada (and probably other languages) for allowing
names on loops with a distinct syntax from goto labels:

<<GOTO_LABEL>>
LOOP_NAME:
loop
exit LOOP_NAME; -- like C's break
end loop LOOP_NAME;
goto GOTO_LABEL;
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Tim Rentsch
2016-11-22 12:01:30 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Francis Glassborow
Post by Keith Thompson
Currently, you can use break or continue for a single level, but you
have to resort to goto for two or more levels. I'd like to use break or
continue for any number of levels, and there's ample precedent for such
a feature in other languages.
OK, could be useful but I actually want to avoid a syntax that can use
the structure label as a destination for a goto which is why I prefer
the suggestion to label the controlled statement.
How does that prevent using it as the target of a goto?
while (1) LABEL: {
// ...
}
// ...
goto LABEL;
is already perfectly legal.
Legal, but pretty unlikely, considering where LABEL: is
positioned. The point is not what the language allows but what
sorts of definitional patterns are commonplace and what sorts
are not.
Post by Keith Thompson
You probably wouldn't *want* to do that,
but if I'm reading the code I still have to verify that there isn't a
`goto LABEL;` somewhere in the function.
Alternatively, a compiler could do that for you, and issue a
(non-fatal) warning if it found one. It seems likely that there
are very few such labels in existing code, so that's a pretty
safe path to take.
Post by Keith Thompson
A new syntax that provides a name for a loop or switch statement,
:LOOP_NAME: while (1) {
// ...
}
would permit the use of LOOP_NAME in a break or continue, but not in a
goto.
I think it's better to use the existing syntax for defining a
label than to intoduce a new one, but even if there is a new
form a label definition IMO it's better for the label to be
after the introductory control phrase, not before:

while (1) :LOOP_NAME: {
// ...
}
Tim Rentsch
2016-11-22 12:02:01 UTC
Permalink
Raw Message
Post by Francis Glassborow
Post by Keith Thompson
Post by luserdroog
Add optional arguments to the break and continue statements
to designate which of a nested set of constructs the abstract
machine should break or continue /to/.
The argument could be a looping keyword (for, while, do) or
'switch'. For a switch in a for-loop, you can now write
`break switch;` to stay in the loop or `break for;` to get
out of it.
If a switch or loop is immediately preceeded by a 'label:',
then that label may also serve to designate /which loop/
in a nested set of loops.
Thanks for all responses. Special thanks to Kaz for
correctly extrapolating a more well-argued explanation
of what I was suggesting. But a bizarre turn occurred
as I started to read the back-and-forth between Keith
and Bart -- viz. I started to agree with Bart.
How to prevent nonsensical or unnecessarily confusing
constructs?
And then Tim's message appears to show the way out.
It does make a lot more sense to put the label on
the controlled statement. This makes `goto label;`
clear and usable.
But if you've gone that far, it's not such a chore
to add a label to the part of the loop you need to
get to.
while (cond) {
switch (thing) {
default: goto continue_cond;
}
continue_cond: ;
}
This way has the tremendous advantage of already
being implemented.
Yes, of *course* you can do any kind of multi-level break or continue
using gotos. You can do single-level break or continue using gotos, and
if the language didn't have break and continue you'd have to.
Currently, you can use break or continue for a single level, but you
have to resort to goto for two or more levels. I'd like to use break or
continue for any number of levels, and there's ample precedent for such
a feature in other languages.
OK, could be useful but I actually want to avoid a syntax that can use
the structure label as a destination for a goto which is why I prefer
the suggestion to label the controlled statement.
Yay! :)
Keith Thompson
2016-11-22 16:36:31 UTC
Permalink
Raw Message
[...]
Post by Tim Rentsch
Post by Francis Glassborow
Post by Keith Thompson
Currently, you can use break or continue for a single level, but you
have to resort to goto for two or more levels. I'd like to use break or
continue for any number of levels, and there's ample precedent for such
a feature in other languages.
OK, could be useful but I actually want to avoid a syntax that can use
the structure label as a destination for a goto which is why I prefer
the suggestion to label the controlled statement.
Yay! :)
Yay? It doesn't prevent using the label as the target of a goto, it
just makes it slightly more awkward.
--
Keith Thompson (The_Other_Keith) kst-***@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Tim Rentsch
2016-11-23 16:53:45 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Tim Rentsch
Post by Francis Glassborow
Post by Keith Thompson
Currently, you can use break or continue for a single level, but you
have to resort to goto for two or more levels. I'd like to use break or
continue for any number of levels, and there's ample precedent for such
a feature in other languages.
OK, could be useful but I actually want to avoid a syntax that can use
the structure label as a destination for a goto which is why I prefer
the suggestion to label the controlled statement.
Yay! :)
Yay? It doesn't prevent using the label as the target of a goto, it
just makes it slightly more awkward.
I don't mean to speak for Francis Glassborow, but maybe the
statement would be better phrased as something like "I want to
avoid a syntax that looks like the structure label has been put
there to serve as a regular goto target." At least that's how I
took it - not whether it the language allows it to be used in
such a fashion, but how it looks like it would be used.

My "yay" was simply an exultation that someone else understands
and agrees with my reasoning here.
Francis Glassborow
2016-11-24 16:31:15 UTC
Permalink
Raw Message
Post by Keith Thompson
[...]
Post by Tim Rentsch
Post by Francis Glassborow
Post by Keith Thompson
Currently, you can use break or continue for a single level, but you
have to resort to goto for two or more levels. I'd like to use break or
continue for any number of levels, and there's ample precedent for such
a feature in other languages.
OK, could be useful but I actually want to avoid a syntax that can use
the structure label as a destination for a goto which is why I prefer
the suggestion to label the controlled statement.
Yay! :)
Yay? It doesn't prevent using the label as the target of a goto, it
just makes it slightly more awkward.
But we really need to distinguish because surely 'going to' a labelled
loop restarts the loop but we do not want that for either break or
continue. In the first case we want to exit to the statement after the
end of the loop. In the second case we want to 'goto' the next
iteration. If achieving this means a new 'label' like syntax I would be
happy but simply having the old label syntax with continue and break
abusing it, I am far from happy and would strongly oppose it.

Francis
Loading...