-
Notifications
You must be signed in to change notification settings - Fork 269
Named blocks to mitigate removing goto #1372
-
Probably the most common use of goto is in error handling: something has gone wrong, jump to the end. The language bakes in three statements which enable different forms of this: continue, break, and return. If goto as a statement is not present in the language then this "jump to the end" use case needs to work well.
In cpp2, the following is one way to do this:
{
inner: do {
...
if error {
break inner;
}
...
} while 0;
// cleanup
}
There are other idioms you could create, but one way or the other it's a surprising idiom.
In other languages such as JavaScript however I can do this, which is more intuitive:
{
inner: {
...
if (error) {
break inner;
}
...
}
// cleanup
}
That’s:
- Less visual clutter
- Less surprising idiom to learn – why should a
do..whileloop be used here when we're not doing any looping? - The syntax you’d guess if you were a beginner to the language, especially coming from other languages.
This a generalization of the unified declaration syntax:
{ /*...*/ } // block
(x: int = init) { /*...*/ } // block with local parameters
:(x: int = init) = { /*...*/ } // lambda
f:(x: int = init) = { /*...*/ } // named function
to this we add
l: { /*...*/ } // named block
l:(x: int = init) { /*...*/ } // named block with local parameters
The "=" is doing the heavy lifting here: it means that this is a declaration, not something to be invoked now.
There's no need for continue to be permitted to reference such a named block.
Secondary observation:
Arguably the presence of this syntax makes it less clear why next needs to exist:
- The main use of
next, to control loop variables, is redundant in the newfor. - The
nextstatement can always be appended to the end of the loop. - In the relatively rare case that an iteration of the loop needs to be aborted, it can be implemented using a named block and
breakstatement, withnextcode following the end of the named block. - It avoids having to teach idiom about when to and when not to use
nextblocks.
I don't want to distract from the core suggestion but the opportunity does further suggest that named blocks could be an overall language generalization and simplification.
Beta Was this translation helpful? Give feedback.
All reactions
-
👍 2 -
❤️ 1
Replies: 1 comment 1 reply
-
Having breakable blocks would be great. I'm not sure about removing next though. Perhaps if you posted some code comparisons?
Beta Was this translation helpful? Give feedback.
All reactions
-
Thanks.
Yes, removing next should really be a separate suggestion if it makes sense. My thinking was as follows:
for (range)
next next_expr
do (i) {
...
if (error) {
continue;
}
...
}
is equivalent to
for (range)
do (i) {
do {
...
if (error) {
continue;
}
...
} while (false);
next_expr;
}
and is actually how cppfront implements it as far as I can tell. With named ranges you can instead do:
for (range)
do (i) {
inner: {
...
if (error) {
break inner;
}
...
}
next_expr;
}
which doesn't feel as unreasonable to expect people to write manually in situations where they would currently use continue and next together, unless those situations are going to be really common and idiomatic.
A similar argument applies for while.
Whether this reduces the value of next below the point at which it's worth including is a question for those who understand its use cases better than me. As a relative outsider, my observations are:
- It doesn't seem likely to be common in new code with good range-based
forloops,..=and..<operators, etc.for (a ..< b) do (i)is the newfor (i = a; i < b; ++i). - When it is seen it could therefore be surprising if you're not used to it so it's another thing to teach.
- When you might want to use it you're probably doing something slightly unusual and so you can't rely on idiom to tell you what you should put in
nextand what you should just put in the body – so when to use it is likely to end up in coding styles and is therefore another thing to teach (unless the coding style is "don't use it"). - Python, another language that just has range-based
forloops and not the Cfor (;;)loops, seems to manage just fine without it.
The counter-argument is that if you're auto-translating code from cpp1 with lots of for (;;) loops that don't convert easily to for (a ..< b) etc. then they more naturally translate to while loops with next clauses. So I can see the value in helping people migrate over from cpp1.
It might be that named blocks at least make it more reasonable to write cpp2 coding style guidelines that recommend against using next in new, non-translated code.
Beta Was this translation helpful? Give feedback.