Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

goto... is it so bad?

64 views
Skip to first unread message

Sushrut Sardeshmukh

unread,
Mar 26, 2007, 3:51:56 AM3/26/07
to
I recently found goto used in a tiny part of (very large C / C++ mix)
code base.
I realized that I have never seen goto before (except college time).
I was so hammered about so called bad effect of goto that I never used
it myself. Nor I thought if it is really so bad. (Since I have never
really seen / used goto, I have not faced any bad effects of it)

I threw this question into my work place group. Only one argument came
up. And it said 'it makes code unreadable'

1. Is it really so bad to use goto? Does any one supports / use it?
2. If goto is so bad, then why C++ still supports it? May be to
maintain compatibility with 'C'. In that case, compiler should give
out a warning, right?
3. For every place where goto was used, there were better ways to plan
the code in the code base I discussed above. But ......is there any
situation where goto is must?


Note: I work for an Investment bank. So I am not into writing stuff
like kernel and device drivers.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

James Kanze

unread,
Mar 26, 2007, 5:53:27 AM3/26/07
to
On Mar 26, 9:51 am, "Sushrut Sardeshmukh" <bestbr...@gmail.com> wrote:
> I recently found goto used in a tiny part of (very large C / C++ mix)
> code base.
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)

> I threw this question into my work place group. Only one argument came
> up. And it said 'it makes code unreadable'

> 1. Is it really so bad to use goto? Does any one supports / use it?

It's not so much the goto in itself that causes the problem.
It's the where you're coming from, at the label. In practice,
deviating from any of the standard structures does make code
unreadable, very, very quickly, and C++ has direct support for
all of the standard structures, so there's never any need for
it.

> 2. If goto is so bad, then why C++ still supports it? May be to
> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?

History. And it's not the sort of thing you're likely to do
accidentally, without meaning to, so it's not really worth the
compiler writers' effort to generate the warning.

> 3. For every place where goto was used, there were better ways to plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?

I think that's the key. In well written code, I don't think
that there is ever a need. On the other hand, perhaps in some
critical situations, where the profiler says you must...
(Typically, the optimizer should be able to do just as well, if
not better, with normal coding structures. But if it doesn't,
you sometimes have to hack it.)

Still, I've been writing software in C or C++ for something like
25 years now, much of it time critical, and I've never needed a
goto.

--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Carl Barron

unread,
Mar 26, 2007, 5:52:48 AM3/26/07
to
In article <1174891072.7...@n76g2000hsh.googlegroups.com>,
Sushrut Sardeshmukh <best...@gmail.com> wrote:

> I recently found goto used in a tiny part of (very large C / C++ mix)
> code base.
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)
>
> I threw this question into my work place group. Only one argument came
> up. And it said 'it makes code unreadable'
>
> 1. Is it really so bad to use goto? Does any one supports / use it?

In the 1960's it was proven that with structured loops [for loops,
while loops, do while loops, and structured if statements such as C or
C++ has the need for goto is eliminated, Use of goto is prone to
produce unreadable and unmaintainable code and is to be avoided chiefly
because of this.

> 2. If goto is so bad, then why C++ still supports it? May be to
> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?

Compilers don't give warnings for using 'ancient' but supported
techniques,

> 3. For every place where goto was used, there were better ways to plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?

I see no real need for goto's in most application code.

Tony Delroy

unread,
Mar 26, 2007, 8:45:40 AM3/26/07
to
> [ are gotos really evil ]...

Some examples of times it may be cleaner to use goto:

- in C++, if you have nested for or while loops, you can't break out
of
multiple loops easily. It may be both faster and more maintainable
to
use a goto.
- in case statements, you sometimes have multiple cases that need
trivial
initial processing, but then do the same processing as some other
label.
If you don't want to factor the common code out to a function, or
there
are reasons not to (like convenient access to local variables), then
you may prefer a goto
- very seldom, you have some really nicely written code then find a
strange
corner case, and you'll be tempted to handle it with a goto rather
than
rework your entire function. Probably most of the time, it's better
to
rework, but perhaps not always.
- there are some famous optimisations for efficient data copying that
rely on gotos to jump into a contiguous set of operation code at a
position that ensures the right number of iterations are run
probably a few others I can't think of off the top of my head...

Walter Bright

unread,
Mar 26, 2007, 8:49:16 AM3/26/07
to
James Kanze wrote:
> And it's not the sort of thing you're likely to do
> accidentally, without meaning to, so it's not really worth the
> compiler writers' effort to generate the warning.

It's trivial to add a warning for using a goto. It isn't done because
there's no demand for it. Like you say, it's not like people
accidentally write semantically valid goto statements.


> I think that's the key. In well written code, I don't think
> that there is ever a need. On the other hand, perhaps in some
> critical situations, where the profiler says you must...
> (Typically, the optimizer should be able to do just as well, if
> not better, with normal coding structures. But if it doesn't,
> you sometimes have to hack it.)

The Digital Mars compilers work by transforming all coding structures
into basic blocks connected by gotos. All optimizations (including loop
invariants, loop induction variables, etc.) are done on this graph.

The algorithms for doing this are classic and well known (I was taught
them in 1982). There's no legitimate reason for a professional compiler
to do any worse with gotos than with structured code.

Walter Bright
http://www.digitalmars.com C, C++, D programming language compilers

Walter Bright

unread,
Mar 26, 2007, 8:47:55 AM3/26/07
to
Sushrut Sardeshmukh wrote:
> I recently found goto used in a tiny part of (very large C / C++ mix)
> code base.
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)
>
> I threw this question into my work place group. Only one argument came
> up. And it said 'it makes code unreadable'
>
> 1. Is it really so bad to use goto?

No. It has its place when you find yourself trying to contort other
control structures that don't quite fit what you want to do.

> Does any one supports / use it?

I regularly use it, probably more than anyone else I know. If you want a
sample of it in professional code, see
http://ftp.digitalmars.com/dmd.zip and grep for goto in /dmd/src/dmd/

> 2. If goto is so bad, then why C++ still supports it?

Probably because of curmudgeons like me who keep using it <g>. Yes, D
has a goto statement, too. Note even if one has religious zeal against
gotos, for machine generated source code having it is pretty handy.

> May be to
> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?

It's not like anyone types 'goto Label;' by accident. If you really want
to scan for them, using "grep" will do just fine. I've been called on
the carpet by QA folks several times for using goto's they found by
using grep. Fun always ensues <g>.

> 3. For every place where goto was used, there were better ways to plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?

One place I use it is in switch statements:

switch (x)
{ case 1:
case 2:
... do some code ...
goto Ldefault;
case 3:
... do some code ...
goto Lcase_5;
case 4:
... do some code ...
Lcase_5:
case 5:
... do some code ...
break;
Ldefault:
default:
... do some code ...
break;
}

In fact, I do it often enough that "goto default" and "goto case expr"
are part of the D programming language's switch statement:

switch (x)
{ case 1:
case 2:
... do some code ...
goto default;
case 3:
... do some code ...
goto case 5;
case 4:
... do some code ...
case 5:
... do some code ...
break;
default:
... do some code ...
break;
}

Other common uses:

1) multilevel breaks.
2) combining block exit cleanup code
3) combining common error exits
4) avoiding reformatting/reorganizing a large block of code to do a
minor edit
5) machine generated source
6) state machines

etc.

Bottom line:

1) yes, it is possible to rewrite every use of goto with some
combination of other structures. Whether the result is better or worse
is up to you, the programmer.

2) if you use goto, be prepared to defend each use of it when the QA
folks or your boss asks you about it.

3) if the guy who signs your paycheck has a thing about not using gotos,
you'd be well advised to not use them <g>.

Zeljko Vrba

unread,
Mar 26, 2007, 8:49:48 AM3/26/07
to
On 2007-03-26, Sushrut Sardeshmukh <best...@gmail.com> wrote:
>
> 1. Is it really so bad to use goto? Does any one supports / use it?
>
No if you use it judiciously. I'd dare say that most people don't know
when goto would be appropriate, so they are given a religious statement
"goto is evil". D. E. Knuth wrote an article "Structured Programming with
GOTO". Here's a link:

http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf

>
> 2. If goto is so bad, then why C++ still supports it? May be to
>

It makes code _clearer_ in certain situations.

>
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?
>

Yes, the simplest example is to bail out of nested loops:

while(a) {
while(b) {
if(something)
goto out_a; // exit the outer loop
}
// more code
}
out_a: // rest of the program

Try to rewrite the above code without using goto. In C++ you _could_
use exceptions for that (although, it's questionable how much more
"readable" that would be), in C you don't even have exceptions.

Another example is hard-coding finite-state automata transitions within
a function.

Other examples could be thought of.

>
> Note: I work for an Investment bank. So I am not into writing stuff
> like kernel and device drivers.
>

It doesn't matter where you work. What is important is not to let
yourself be brainwashed :)

Alf P. Steinbach

unread,
Mar 26, 2007, 10:12:25 AM3/26/07
to
* Sushrut Sardeshmukh:

> I recently found goto used in a tiny part of (very large C / C++ mix)
> code base.
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)
>
> I threw this question into my work place group. Only one argument came
> up. And it said 'it makes code unreadable'
>
> 1. Is it really so bad to use goto? Does any one supports / use it?

For manually written code 'goto' is in most cases better expressed by
'break', 'continue' or 'return'.

A case might be made for breaking out of a doubly or triply nested loop,
but then, a case might be made for doing that using 'return'.

On the other hand, I believe tools such 'lex' still generate
'goto'-based state machines. At least they used to.


> 2. If goto is so bad, then why C++ still supports it?

C++ supports low level programming in general.

Remove all those language features and you have a language with all the
problems associated with low level programming, and none of the advantages.


> May be to
> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?

Why?


> 3. For every place where goto was used, there were better ways to
plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?

No.

But then, the same can be said about any language feature.


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Francis Glassborow

unread,
Mar 26, 2007, 10:18:09 AM3/26/07
to
James Kanze wrote:
> I think that's the key. In well written code, I don't think
> that there is ever a need. On the other hand, perhaps in some
> critical situations, where the profiler says you must...
> (Typically, the optimizer should be able to do just as well, if
> not better, with normal coding structures. But if it doesn't,
> you sometimes have to hack it.)
>
> Still, I've been writing software in C or C++ for something like
> 25 years now, much of it time critical, and I've never needed a
> goto.
In much the same time span I have never had anyone offer me a convincing
example of where it solved a problem other than with poorly designed
code. In addition I have a sneaky suspicion that it causes problems with
exception safety, particularly as it has function scope rather than
block scope.

Quite apart from readability issues its use also creates maintenance ones.
Francis Glassborow

Francis Glassborow

unread,
Mar 26, 2007, 10:58:22 AM3/26/07
to
Tony Delroy wrote:
>> [ are gotos really evil ]...
>
> Some examples of times it may be cleaner to use goto:
>
> - in C++, if you have nested for or while loops, you can't break out
> of
> multiple loops easily. It may be both faster and more maintainable
> to
> use a goto.

Any speed advantage is minuscule (well it might be faster for a naive
programmer to 'design' and write the resulting code?). However, nested
loops, conditionals etc. are almost always a maintenance nightmare and I
do not see how using goto would reduce that.

> - in case statements, you sometimes have multiple cases that need
> trivial
> initial processing, but then do the same processing as some other
> label.
> If you don't want to factor the common code out to a function, or
> there
> are reasons not to (like convenient access to local variables), then
> you may prefer a goto

In 25 years of programming in C and over 15 of doing so in C++ I cannot
recall a single time when I would have wanted to do that.

> - very seldom, you have some really nicely written code then find a
> strange
> corner case, and you'll be tempted to handle it with a goto rather
> than
> rework your entire function. Probably most of the time, it's better
> to
> rework, but perhaps not always.

That is a matter of opinion, and not one I share. That temptation is
exactly why goto is such a problem.

> - there are some famous optimisations for efficient data copying that
> rely on gotos to jump into a contiguous set of operation code at a
> position that ensures the right number of iterations are run
> probably a few others I can't think of off the top of my head...
>
>

Yes, and though such things are amusing, they also have no place in
modern code.

Of course the above are my (strongly held) opinions but I would dearly
like to see a single real example. Every goto I have ever encountered
disappears when the code is redesigned to be simpler, more readable and
more maintainable.

Francis Glassborow

unread,
Mar 26, 2007, 10:59:20 AM3/26/07
to
Zeljko Vrba wrote:
> Yes, the simplest example is to bail out of nested loops:
>
> while(a) {
> while(b) {
> if(something)
> goto out_a; // exit the outer loop
> }
> // more code
> }
> out_a: // rest of the program
>
> Try to rewrite the above code without using goto. In C++ you _could_
> use exceptions for that (although, it's questionable how much more
> "readable" that would be), in C you don't even have exceptions.
>

But you are assuming that that code itself is necessary. Without knowing
more details it is hard to rewrite but given the context I would expect
to redesign the code without much trouble.

However:

while(a) {
while(b and not something){
// code which might change the
// truth value of something
}
if(something) break;
// more code
}

Now it is immediately clear that the inner loop is only executed until
either 'b' or 'not something' evaluates as false. And if you need to
micro-optimize you can write 'not something and b' if the loop normally
terminates on something becoming true.

It is also clear that the outer loop terminates when something is true.
Though I do try to avoid using break to exit a loop (unless it is the
only way out so I might actually write:

while(true){
while(b and not something){
// code which might change the
// truth value of something
}
if(something or not a) break;
// more code
}

Which also makes it clear that the outer loops termination condition is
actually that a be true and something be false.

And yes, you can keep coming up with counter examples, and I can keep
shooting them down. That is just tedious.

Walter's upthread examples are exactly what I would expect from someone
who (like me) learnt his craft with assembler. The problem caused to
maintenance is that you have to check every change at both the come from
and arrive at point.

James Hopkin

unread,
Mar 26, 2007, 11:00:16 AM3/26/07
to
On Mar 26, 3:18 pm, Francis Glassborow <franc...@robinton.demon.co.uk>
wrote:

>
> In much the same time span I have never had anyone offer me a convincing
> example of where it solved a problem other than with poorly designed
> code. In addition I have a sneaky suspicion that it causes problems with
> exception safety, particularly as it has function scope rather than
> block scope.
>

I can't think of any exception safety problems with goto. In fact, I
look at it the other way round: exception-safe code is also 'goto
safe' (and 'break/continue safe' and 'early return safe').

I don't have the combined 50 years experience of you two ;-), but FWIW
I haven't come across a genuine use for goto either. I've just used it
once or twice as the quickest way to try something out, but there's
always been a pretty obvious, much better way of writing the code.


James

Daniel T.

unread,
Mar 26, 2007, 11:00:28 AM3/26/07
to
"Sushrut Sardeshmukh" <best...@gmail.com> wrote:

> I recently found goto used in a tiny part of (very large C / C++ mix)
> code base.
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)
>
> I threw this question into my work place group. Only one argument came
> up. And it said 'it makes code unreadable'

http://www.acm.org/classics/oct95/

> 1. Is it really so bad to use goto? Does any one supports / use it?

It isn't the word itself that is bad of course. If used responsibly, if
the code structure is maintained, there is nothing especially wrong with
it. "The go to statement as it stands is just too primitive; it is too
much an invitation to make a mess of one's program." (Dijkstra) Of
course if you never accept the invitation...

Stephen Howe

unread,
Mar 26, 2007, 5:18:52 PM3/26/07
to
> while(true){
> while(b and not something){
> // code which might change the
> // truth value of something
> }
> if(something or not a) break;
> // more code
> }

What if a is false to start with?
Your version will start executing the the inner while loop while the
original goto version, the outer while loop wont even start.
That 2nd set of while loops is not isomorphic to the original while loop
with goto.

> And yes, you can keep coming up with counter examples, and I can keep
> shooting them down.

Not with incorrect replacements you cant.

I dont regard those transformed while loops as clearer, in fact they look
plain ugly, worse than the original while loops with 1 goto.
If the outer loop is really controlled by a, why not express that intent
with "while (a)"?
If the inner loop is really controlled by b, why not express that intent
with "while (b)"?
You have replaced the working code with some ugly contortions, far worse
than the goto alternative.

For me, it is not "use goto" or "not use goto" that is the rule.
It is "which looks clearer?", and sometimes, particularly with deeply nested

loops, the goto version does looks clearer.
And clearer code is more maintainable.

Cheers

Stephen Howe

Edward Rosten

unread,
Mar 26, 2007, 5:18:14 PM3/26/07
to
On Mar 26, 3:53 am, "James Kanze" <james.ka...@gmail.com> wrote:
> On Mar 26, 9:51 am, "Sushrut Sardeshmukh" <bestbr...@gmail.com> wrote:

> It's not so much the goto in itself that causes the problem.

So, you're a fan of intercal? :-)

> It's the where you're coming from, at the label. In practice,
> deviating from any of the standard structures does make code
> unreadable, very, very quickly, and C++ has direct support for
> all of the standard structures,

I wouldn't have said so, exactly. Some other languages (for instance,
BASH) allow break and continue to take a number which indicates the
nesting level to operate on. Jumping out of a nested loop requires a
goto.

> so there's never any need for
> it.

I work with images, so I frequently have a loop over rows and a loop
columns (as opposed to a loop over elements in a linear container).
This means I occasionally need gotos (well, more often than 1 in 25
years, at any rate).


> > 3. For every place where goto was used, there were better ways to
plan
> > the code in the code base I discussed above. But ......is there any
> > situation where goto is must?
>
> I think that's the key. In well written code, I don't think
> that there is ever a need.

I've also found them useful in machine generated code. Machines don't
have a problem getting it right.

I've also used it for small, ad-hoc parsers. For instance, consider
parsing coordinates structured like this:
(<ws><integer><ws>,<ws><integer><ws>)
<ws> stands for optional whitespace. The following function will parse
this, and set the bad bit if the data has the incorrect structure:

istream& operator>>(Coordinate& ref)
{
unsigned char c = is.get();

if(is.eof())
return is;

if(c == '(' )
{
is >> std::ws >> ref.x >> std::ws;

if(is.get() != ',')
goto bad;

is >> std::ws >> ref.y >> std::ws;

if(is.get() != ')')
goto bad;
}

bad:
is.setstate(std::ios_base::badbit);

return is;
}


It's got gotos. Is there a much cleaner way?

-Ed

Stephen Howe

unread,
Mar 26, 2007, 5:13:23 PM3/26/07
to
> In much the same time span I have never had anyone offer me a convincing
> example of where it solved a problem other than with poorly designed code.

What about the example illustrating goto in the K & R book - multiple loops
and you need to jump out of all of them?
goto is what I use in these circumstances when there is no alternative and
return will not do.

And what is the alternative to this?
1. Artificially creating extra boolean variables to see which loops need
exiting and are checked in the loop control structures?
2. Artificially hoisting the multiple loop block code and placing it a
function, just so that you can use "return"?

The options 1 & 2 are so dreadful, so poor, that I reach for goto. 1 & 2
suffer from their own readability issues - I have to write far more lines of

code than the goto alternative. I use goto roughly once a year in code,
usually for exit & cleanup situations.

Over the years I have seen some mendbendingly strange use of control
structures written just to avoid using goto.

Stephen Howe

Vladimir Marko

unread,
Mar 26, 2007, 5:28:05 PM3/26/07
to
On 26 Mar, 13:47, Walter Bright <wal...@digitalmars-nospamm.com>
wrote:

> Sushrut Sardeshmukh wrote:
> > 1. Is it really so bad to use goto?
>
> No. It has its place when you find yourself trying to contort other
> control structures that don't quite fit what you want to do.
>
> > Does any one supports / use it?
>
> I regularly use it, probably more than anyone else I know. If you want a
> sample of it in professional code, see http://ftp.digitalmars.com/dmd.zip
> and grep for goto in /dmd/src/dmd/

That's pure C, isn't it? goto is certainly useful in C, but there are
better tools for the job in C++.

Making a quick search for goto in the whole dmd.zip I had a look into
a few
random .d files. And I'm very curious, it's not written in full D is
it?
May be a very small subset? (If it was written in full D, I would have
to
state that either D is comparable with C89 or the programmer is
incompetent
or [s]he is deliberately obfuscating the code.)

>
> > 2. If goto is so bad, then why C++ still supports it?

> > May be to
> > maintain compatibility with 'C'. In that case, compiler should give
> > out a warning, right?
>
> It's not like anyone types 'goto Label;' by accident. If you really want
> to scan for them, using "grep" will do just fine. I've been called on
> the carpet by QA folks several times for using goto's they found by
> using grep. Fun always ensues <g>.

I would easily defend many uses of goto in C code. On the other hand,
defending frequent use of goto in C++ might prove impossible.

>
> > 3. For every place where goto was used, there were better ways to
plan
> > the code in the code base I discussed above. But ......is there any
> > situation where goto is must?
>
> One place I use it is in switch statements:
>
> switch (x)

> ...
> }

A switch statement is already a nicely packaged bunch of gotos, so
adding
a few more feels quite acceptable.

> Other common uses:
>
> 1) multilevel breaks.

The last time I saw reasonable 3 nested loops was Floyd-Warshal
algorithm
many years ago. And whenever I needed to break out of 2 nested loops
it
was either by return, or I just rewrote the inner loop using find/
find_if
anyway because _I_ find it more readable.

> 2) combining block exit cleanup code

I thought that's what RAII is for in C++.

> 3) combining common error exits

Ehm, is "goto nomatch;" more readable than "return nomatch;" where
nomatch
is a local enumerator defined at the _beginning_ of the function
(where it
nicely documents the return values)?

> 4) avoiding reformatting/reorganizing a large block of code to do a
> minor edit

Minor edit today, minor edit tomorrow, total mess in a week.

> 5) machine generated source

Agreed.

> 6) state machines

May be, if performance is of utmost importance.

> Bottom line:
>
> 1) yes, it is possible to rewrite every use of goto with some
> combination of other structures. Whether the result is better or worse
> is up to you, the programmer.

Of course. However, the effort required to make the code with gotos
readable is usually much higher than with other tools available in C+
+.

Regards
Vladimir Marko

Daniel Krügler

unread,
Mar 26, 2007, 5:20:34 PM3/26/07
to

James Hopkin schrieb:

> I don't have the combined 50 years experience of you two ;-), but FWIW
> I haven't come across a genuine use for goto either. I've just used it
> once or twice as the quickest way to try something out, but there's
> always been a pretty obvious, much better way of writing the code.

<confession>
(Slightly redfaced): Interestingly I can remember that I used
goto once, but it was not in a C or C++ program but instead
in a Pascal program, where the code computed a hash value.
I searched in my old sources and here we go(to):

case Len of
11: goto Pos11;
10: goto Pos10;
9: goto Pos09;
8: goto Pos08;
7: goto Pos07;
6: goto Pos06;
5: goto Pos05;
4: goto Pos04;
3: goto Pos03;
2: goto Pos02;
1: goto Pos01;
else goto Pos00;
end;

Pos11: c := c + (UInt32(Key[10]) shl 24);
Pos10: c := c + (UInt32(Key[9]) shl 16);
Pos09: c := c + (UInt32(Key[8]) shl 8);
// The first byte of c is reserved for the length:
Pos08: b := b + (UInt32(Key[7]) shl 24);
Pos07: b := b + (UInt32(Key[6]) shl 16);
Pos06: b := b + (UInt32(Key[5]) shl 8);
Pos05: b := b + UInt32(Key[4]);
Pos04: a := a + (UInt32(Key[3]) shl 24);
Pos03: a := a + (UInt32(Key[2]) shl 16);
Pos02: a := a + (UInt32(Key[1]) shl 8);
Pos01: a := a + UInt32(Key[0]);
Pos00: // case 0: nothing left to add

As you see, this code effectively simulated
a C switch statement ;-)
</confession>

Greetings from Bremen,

Daniel Kr|gler

Walter Bright

unread,
Mar 26, 2007, 5:21:55 PM3/26/07
to
Francis Glassborow wrote:
> It is also clear that the outer loop terminates when something is true.
> Though I do try to avoid using break to exit a loop (unless it is the
> only way out so I might actually write:
>
> while(true){
> while(b and not something){
> // code which might change the
> // truth value of something
> }
> if(something or not a) break;
> // more code
> }
>
> Which also makes it clear that the outer loops termination condition is
> actually that a be true and something be false.

Whether that is clearer or not is a personal matter of style and
opinion. To me, this example is less clear than the goto version. One
reason I use gotos is to avoid code duplication and duplicate testing of
conditionals (the "something" in your example). I find duplication to be
a maintenance problem because I have to a) visually check to ensure they
really are duplicates and b) remember that when I change one, I must
change the other in sync. Even worse, the need to move "something" out
of the inner loop may require declaring more variables and moving
declarations of variables out of inner scopes, and spreading the
initialization/use of such variables across larger swaths of code. For
example:

while(a) {
while(b) {
if(foo())


goto out_a; // exit the outer loop
}
// more code
}
out_a: // rest of the program

becomes:

while(true){
bool tmp = false;
while(b && !(tmp = (foo() != 0))){


// code which might change the
// truth value of something
}

if(tmp or not a) break;
// more code
}

I have to look at that pretty carefully to see if it really is the same
as the simple goto version.

> And yes, you can keep coming up with counter examples, and I can keep
> shooting them down. That is just tedious.

I think we can all agree that since it's been proven that one can always
be transformed into the other, it is pointless to produce counter
examples showing that it can be done.

> Walter's upthread examples are exactly what I would expect from someone
> who (like me) learnt his craft with assembler.

Basic, FORTRAN, and assembler, all of which relied on goto <g>.

> The problem caused to
> maintenance is that you have to check every change at both the come from
> and arrive at point.

As opposed to checking the duplication of code (even if the optimizer
can get rid of the duplication, the maintenance programmer still has to
see it, check it, etc.)

I don't use goto gratuitously - if a structured statement will fit, I'll
use that instead. If it doesn't, I won't. I try not to use a crowbar as
a hammer, either, even if it can drive nails <g>. I might also add that
I use fewer goto's in D programming because D has a richer panopoly of
structured statements that obviate many uses of gotos, such as
multilevel breaks (useful in the above example) and scope guards.

Kaba

unread,
Mar 26, 2007, 5:26:47 PM3/26/07
to
> 1. Is it really so bad to use goto? Does any one supports / use it?

Aside the readability issues, here's a more severe one. This one is from
the C++ reference book "C++ in a nutshell". Page 93: (talking about the
goto statement)

"Jumping into a block is usually a bad idea. In particular, if the jump
bypasses the declaration of an object, the results are undefined unless
the object has POD type and no initializer."

Now imagine generic code combined with goto's and someone changing a
type from a native to a user-defined type. Then again, you don't even
need genericity to be able to imagine similar situations.

--
Kalle Rutanen
http://kaba.hilvi.org

Niels Aan de Brugh

unread,
Mar 26, 2007, 5:29:05 PM3/26/07
to
Sushrut Sardeshmukh wrote:

> 1. =C2=A0 =C2=A0 =C2=A0Is it really so bad to use goto? Does any one su=
pports / use it?

No, I never really had to, but I wouldn't avoid it per se. I regularly se=
e
people using continue, break (in loops) and multiple returns, and that's
almost as messy as a goto. So there's no real reason for goto to be such =
a
pariah among keywords.

> 2. =C2=A0 =C2=A0 =C2=A0If goto is so bad, then why C++ still supports i=


t? May be to
> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?

As others have pointed out, goto is part of C++ so why the warning? Warni=
ngs
should be about possible unwanted/unforeseen behavior, not coding style (=
we
have tools like TICS for that).

You might be interested in this:

http://kerneltrap.org/node/553/2131

Although I don't agree with Linus' rather harsh opinion about Wirth and
(especially) Dijkstra the articles do bring up a few valid points.

N.

Walter Bright

unread,
Mar 26, 2007, 6:13:43 PM3/26/07
to
Vladimir Marko wrote:
> On 26 Mar, 13:47, Walter Bright <wal...@digitalmars-nospamm.com>
> wrote:
>> I regularly use it, probably more than anyone else I know. If you want a
>> sample of it in professional code, see http://ftp.digitalmars.com/dmd.zip
>> and grep for goto in /dmd/src/dmd/
>
> That's pure C, isn't it? goto is certainly useful in C, but there are
> better tools for the job in C++.

It's C++. The front end is in C++ to make it easier to connect with
existing back ends, which are likely to be in C or C++.


>> 2) combining block exit cleanup code
> I thought that's what RAII is for in C++.

Yes, you can do it with RAII, but creating classes for the sole purpose
of manipulating control flow (rather than storing state) is a
contortion, not clarification.

My favorite solution for this is actually the scope guard statement:
http://www.digitalmars.com/d/exception-safe.html
invented by Andrei Alexandrescu and Petru Marginean


>> 3) combining common error exits
>
> Ehm, is "goto nomatch;" more readable than "return nomatch;" where
> nomatch
> is a local enumerator defined at the _beginning_ of the function
> (where it
> nicely documents the return values)?

6 of one, half dozen of the other.

red floyd

unread,
Mar 26, 2007, 10:59:10 PM3/26/07
to
Stephen Howe wrote:
>> In much the same time span I have never had anyone offer me a convincing
>> example of where it solved a problem other than with poorly designed code.
>
> What about the example illustrating goto in the K & R book - multiple loops
> and you need to jump out of all of them?
> goto is what I use in these circumstances when there is no alternative and
> return will not do.
>
> And what is the alternative to this?
> 1. Artificially creating extra boolean variables to see which loops need
> exiting and are checked in the loop control structures?
> 2. Artificially hoisting the multiple loop block code and placing it a
> function, just so that you can use "return"?

In C++, you have the option of throwing an exception as well. In C, I
agree that

for (...)
{
for (...)
{
if (some condition)
goto disaster;
}
}
disaster:
loop end code...

isn't bad.

red floyd

unread,
Mar 26, 2007, 10:59:30 PM3/26/07
to
Kaba wrote:

>
> "Jumping into a block is usually a bad idea. In particular, if the jump
> bypasses the declaration of an object, the results are undefined unless
> the object has POD type and no initializer."
>


In C99, goto into a block is illegal. ISO/IEC 9899:1999 6.8.6.1/1

In C++, jumping into a block is legal : ISO/IEC 14882:2003 6.7/3, but
the quoted restriction applies.

--

Kirit Sælensminde

unread,
Mar 26, 2007, 11:08:11 PM3/26/07
to
On Mar 27, 4:18 am, "Edward Rosten" <Edward.Ros...@gmail.com> wrote:
> I've also used it for small, ad-hoc parsers. For instance, consider
> parsing coordinates structured like this:
> (<ws><integer><ws>,<ws><integer><ws>)
> <ws> stands for optional whitespace. The following function will parse
> this, and set the bad bit if the data has the incorrect structure:
>
> istream& operator>>(Coordinate& ref)
> {
> unsigned char c = is.get();
>
> if(is.eof())
> return is;
>
> if(c == '(' )
> {
> is >> std::ws >> ref.x >> std::ws;
>
> if(is.get() != ',')
> goto bad;
>
> is >> std::ws >> ref.y >> std::ws;
>
> if(is.get() != ')')
> goto bad;
> }
>
> bad:
> is.setstate(std::ios_base::badbit);
>
> return is;
>
> }

Do you really mean to set badbit on 'is' after successfully parsing?
It seems to me that your use of goto has introduced a bug.

How about this?

istream& operator>>(Coordinate& ref)
{
unsigned char c = is.get();

if(is.eof())
return is;

if(c == '(' )
{
is >> std::ws >> ref.x >> std::ws;

if(is.get() != ',') {


is.setstate(std::ios_base::badbit);
return is;
}

is >> std::ws >> ref.y >> std::ws;

if(is.get() != ')')
is.setstate(std::ios_base::badbit);

} else is.setstate(std::ios_base::badbit);

return is;

}

NB - Not been through a compiler.

This version doesn't do the same thing though. If the parse is
successful then it doesn't set badbit. I don't think that the return
after the first check is really needed as setting badbit will be
remembered and the rest of the parse attempts can be left to silently
re-fail.

In terms of properly usable code though this also leaves something to
be desired. It will leave the Coordinate partially initialised on a
syntax error and it doesn't report what the error is. Personally I'd
prefer to use exceptions for this sort of error.


K

Joe Gottman

unread,
Mar 26, 2007, 11:09:56 PM3/26/07
to
Edward Rosten wrote:

> I wouldn't have said so, exactly. Some other languages (for instance,
> BASH) allow break and continue to take a number which indicates the
> nesting level to operate on. Jumping out of a nested loop requires a
> goto.

I dislike that construct. It can be tedious to count how deep you
are in a series of nested loops, and if someone adds or removes a layer
your program's behavior silently changes. I much prefer Perl's idiom of
named loops.

Joe Gottman

Howard Hinnant

unread,
Mar 26, 2007, 11:08:24 PM3/26/07
to
I'm not terribly fond of me-too posts. But I kept trying to contribute
to this one and, dang it, Walter kept repeatedly expressing my own
thoughts better than I could. :-)

In article <9umdnX_yMN5qj5Xb...@comcast.com>,
Walter Bright <wal...@digitalmars-nospamm.com> wrote:

> I don't use goto gratuitously - if a structured statement will fit, I'll
> use that instead. If it doesn't, I won't. I try not to use a crowbar as
> a hammer, either, even if it can drive nails <g>. I might also add that
> I use fewer goto's in D programming because D has a richer panopoly of
> structured statements that obviate many uses of gotos, such as
> multilevel breaks (useful in the above example) and scope guards.

-Howard

Carl Barron

unread,
Mar 26, 2007, 11:06:40 PM3/26/07
to
In article <1174931686.9...@l75g2000hse.googlegroups.com>,
Edward Rosten <Edward...@gmail.com> wrote:

>
> I've also found them useful in machine generated code. Machines don't
> have a problem getting it right.
>
> I've also used it for small, ad-hoc parsers. For instance, consider
> parsing coordinates structured like this:
> (<ws><integer><ws>,<ws><integer><ws>)
> <ws> stands for optional whitespace. The following function will parse
> this, and set the bad bit if the data has the incorrect structure:
>

why badbit since the usual meaning of failbit includes syntax error of
the textual representation of the expected type? using failbit makes
it simpler just to set the failbit when the chars read are wrong, the
system will handle the ints, and stop inputting if the failbit of the
stream is set.

> istream& operator>>(istream &is,Coordinate& ref)
> {
char c;
if(is >> c && c!='(') is.setstate(std::ios_base::failbit);
is >> ref.x)
if(is >> c && c!=',') is.setstate(std::ios_base::failbit);
is >> ref.y;
if(is >> c && c!=')') is.setstate(std::ios_base::failbit);
return is;
}

looks cleaner to me and is definitely shorter.

Kirit Sælensminde

unread,
Mar 26, 2007, 11:09:29 PM3/26/07
to
On Mar 26, 2:51 pm, "Sushrut Sardeshmukh" <bestbr...@gmail.com> wrote:
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)

To really understand the horror of goto you need to look at how older
languages dealt with control flow. Early BASIC for example. As you
probably don't have access to a BASIC interpreter you can simulate the
same sort of thing in C++ by following these simple rules (these are
off the top of my head):

* Every line must have a numbered label. Numbers must not be out of
order.
* Each line may have only a single statement.
* You may use functions, but you may not pass any arguments. All
variables must be global.
* You may not use braces except when using a for loop. for loops may
be nested.
* for loops may only have numeric counters.
* No while or do loops.
* You may use std::vector, std::string, int and float. std::vectors
may nest, i.e. you can have arrays of arrays.

This leads to things like this:

int main() {
L10: std::out << "Hello world" << std::endl;
L20: goto L10;
}

A simple if statement looks like this:

L50: if ( somecondition ) goto L100;
L60: // else part
L90: goto L150;
L100: // somecondition part
L150: // post if statement code

Now image that your program has a few hundred lines. Now imagine one
that has a few thousand.


K

Anand Hariharan

unread,
Mar 26, 2007, 11:06:02 PM3/26/07
to
On Mar 26, 2:51 am, "Sushrut Sardeshmukh" <bestbr...@gmail.com> wrote:
(...)
> 1. Is it really so bad to use goto? Does any one supports / use it?
> 2. If goto is so bad, then why C++ still supports it? May be to

> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?
> 3. For every place where goto was used, there were better ways to plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?
>

If your project is entirely in C, use of goto is unavoidable IMHO.
One would typically find code like so:

void Func(void)
{
/* Declare all your pointers at the very top, and initialise to NULL
right at beginning */

/* Initialise Return Code to Failure */

/* Keep checking for return codes of every function you call. Persist
with other checks (e.g., invariants). If something fails, set Func's
return code and jump to "CleanUp_Label" */


/* Set Return Code to Success */
CleanUp_Label:

/* For each pointer that represents a resource, if pointer not NULL,
release resource corresponding to pointer */

}

Trying to avoid goto just because it is religious is not fruitful. Of
course, in C++, one has exceptions and RAII, so the need for goto is
far less.

- Anand

Howard Hinnant

unread,
Mar 26, 2007, 11:08:24 PM3/26/07
to
I'm not terribly fond of me-too posts. But I kept trying to contribute
to this one and, dang it, Walter kept repeatedly expressing my own
thoughts better than I could. :-)

> I don't use goto gratuitously - if a structured statement will fit, I'll
> use that instead. If it doesn't, I won't. I try not to use a crowbar as
> a hammer, either, even if it can drive nails <g>. I might also add that
> I use fewer goto's in D programming because D has a richer panopoly of
> structured statements that obviate many uses of gotos, such as
> multilevel breaks (useful in the above example) and scope guards.

-Howard

Phlip

unread,
Mar 27, 2007, 3:24:57 AM3/27/07
to
Sushrut Sardeshmukh wrote:

> 1. Is it really so bad to use goto? Does any one supports / use it?

'goto' is a "design smell". It is a hint that your design probably has
other
faults, and you should follow your nose to find what they are.

> 2. If goto is so bad, then why C++ still supports it?

Because a language you can't abuse is a language you can't entirely use.

Language designers are not nannies, who think they must hold our hands
as we
learn to walk. The languages that slavishly enforce their designers' pet
principles are typically the worst ones in the world.

> 3. For every place where goto was used, there were better ways to
> plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?

Suppose you notice a goto. If it actually damages your ability to read or
refactor a function, then that design smell might lead you to notice the
function is way too long. If the function is short, the label must be near
the goto, so it would be less of a problem.

That leads to the ideal that the goto could be replaced by a block
structure - an if or a do-while.

Good code might still use 'goto' to exit from a nested loop. And this
represents code that could refactor into an even better function, and use
'return' to exit the nested loop.

You probably saw code without unit tests. (Look them up - they are
super-important.) Without tests, as soon as a stretch of code works, you
typically resist changing its design. So if a 'goto' made the final cut,
the
risk of removing it may seem higher than the benefit of more readable
code -
especially if you can't make its function shorter or put its loops into
functions. Because you don't have unit tests to help rapidly detect if your
change was safe.

> Note: I work for an Investment bank. So I am not into writing stuff
> like kernel and device drivers.

Then you should be using a soft language (softer than Java, for example)
that gives lots of room for unit tests, and advanced structures (such as
block-closures) that give even fewer excuses to use 'goto'. Or even the
design smells that are more subtle and harder to spot!

(Under the burden of occassionally making you >cough< throw execptions for
normal control-flow...)

--
Phlip
http://flea.sourceforge.net/PiglegToo_1.html

Edward Rosten

unread,
Mar 27, 2007, 3:22:22 AM3/27/07
to
On Mar 26, 9:08 pm, "Kirit Sælensminde" <kirit.saelensmi...@gmail.com>
wrote:

> Do you really mean to set badbit on 'is' after successfully parsing?
> It seems to me that your use of goto has introduced a bug.

The copy/paste bug. I cut off a chunk of the parser which deals with
other cases, and deleted a "return is" by mistake.

> In terms of properly usable code though this also leaves something to
> be desired. It will leave the Coordinate partially initialised on a
> syntax error and it doesn't report what the error is. Personally I'd
> prefer to use exceptions for this sort of error.

Now consider a more complicated case, where the coordinate is never
left in a partially initialized state. In my version, that code would
all go in the bit after "bad:". Without the goto, this would be
duplicated.

Perhaps I should have included the full version which will accept (a,
b) [a b] or just a b, and cleans up properly.

I think made it too brief to make my point.

-Ed

Gerhard Menzl

unread,
Mar 27, 2007, 6:53:11 AM3/27/07
to
Walter Bright wrote:

> Yes, you can do it with RAII, but creating classes for the sole
> purpose of manipulating control flow (rather than storing state) is a
> contortion, not clarification.

An interesting point of view. Do you also consider replacing
switch(type) constructs by class hierarchies as a contortion?

--
Gerhard Menzl

Non-spammers may respond to my email address, which is composed of my
full name, separated by a dot, followed by at, followed by "fwz",
followed by a dot, followed by "aero".

James Kanze

unread,
Mar 27, 2007, 6:53:01 AM3/27/07
to
On Mar 26, 2:49 pm, Walter Bright <wal...@digitalmars-nospamm.com>
wrote:
> James Kanze wrote:
> > And it's not the sort of thing you're likely to do
> > accidentally, without meaning to, so it's not really worth the
> > compiler writers' effort to generate the warning.

> It's trivial to add a warning for using a goto. It isn't done because
> there's no demand for it. Like you say, it's not like people
> accidentally write semantically valid goto statements.

Exactly. I've never seen a goto which "accidentally" crept in.
(Come to think of it, I don't think I've ever seen a goto in any
of the C or C++ code I've read, except in some machine generated
code.)

> > I think that's the key. In well written code, I don't think

> > that there is ever a need. On the other hand, perhaps in some
> > critical situations, where the profiler says you must...
> > (Typically, the optimizer should be able to do just as well, if
> > not better, with normal coding structures. But if it doesn't,
> > you sometimes have to hack it.)

> The Digital Mars compilers work by transforming all coding structures
> into basic blocks connected by gotos. All optimizations (including loop
> invariants, loop induction variables, etc.) are done on this graph.

> The algorithms for doing this are classic and well known (I was taught
> them in 1982). There's no legitimate reason for a professional compiler
> to do any worse with gotos than with structured code.

That is, I believe, the usual process. I do know of at least
one compiler (for Modula-2), however, that based itself on the
explicitly written structures, and didn't even try to optimize
if there was a goto. According to the authors of the compiler,
this resulted in much faster optimization, at no cost to typical
(Modula-2) programs.

Of course, most of the optimizing technology that you would have
been taught in 1982 was developed for Fortran, where you didn't
have that luxury. One could argue that, today, we could do
better. Still, it's a tried and true technology, and if I were
writing a compiler today, I'd probably use it, not because I
want to support goto particularly well, but because I know it
works, given the number of compilers which use it.

--
James Kanze (GABI Software) mailto:james...@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34


--

James Kanze

unread,
Mar 27, 2007, 6:53:05 AM3/27/07
to
On Mar 26, 11:18 pm, "Edward Rosten" <Edward.Ros...@gmail.com> wrote:
> On Mar 26, 3:53 am, "James Kanze" <james.ka...@gmail.com> wrote:

> > It's the where you're coming from, at the label. In practice,
> > deviating from any of the standard structures does make code
> > unreadable, very, very quickly, and C++ has direct support for
> > all of the standard structures,

> I wouldn't have said so, exactly. Some other languages (for instance,
> BASH) allow break and continue to take a number which indicates the
> nesting level to operate on. Jumping out of a nested loop requires a
> goto.

Which is a sure recepe for unreadable, and especially for
fragile programs. (In fact, I never use break in C++, except to
end a case in a switch.)

> > so there's never any need for
> > it.

> I work with images, so I frequently have a loop over rows and a loop
> columns (as opposed to a loop over elements in a linear container).
> This means I occasionally need gotos (well, more often than 1 in 25
> years, at any rate).

I can see that being a case where you might actually have nested
loops (as opposed to putting the inner loop in another
function), but I still don't see why terminating a nested loop
is any different than terminating a single loop. (But as I
said, I don't use break even with a single loop.)

> > > 3. For every place where goto was used, there were better ways to plan
> > > the code in the code base I discussed above. But ......is there any
> > > situation where goto is must?

> > I think that's the key. In well written code, I don't think
> > that there is ever a need.

> I've also found them useful in machine generated code. Machines don't
> have a problem getting it right.

I can agree there. There's no necessity for machine generated
code to be "well written". Not only does the machine have no
problem getting it right in the first place, no one has to read
and understand the code it generates either.

> I've also used it for small, ad-hoc parsers. For instance, consider
> parsing coordinates structured like this:
> (<ws><integer><ws>,<ws><integer><ws>)
> <ws> stands for optional whitespace. The following function will parse
> this, and set the bad bit if the data has the incorrect structure:

> istream& operator>>(Coordinate& ref)
> {
> unsigned char c = is.get();
> if(is.eof())
> return is;

Attention: this is a dangerous error. You don't read a value,
but you don't position anything to tell the caller that you
haven't read it.

> if(c == '(' )
> {
> is >> std::ws >> ref.x >> std::ws;
>
> if(is.get() != ',')
> goto bad;
>
> is >> std::ws >> ref.y >> std::ws;
>
> if(is.get() != ')')
> goto bad;
> }
>
> bad:
> is.setstate(std::ios_base::badbit);
>
> return is;
>
> }

> It's got gotos. Is there a much cleaner way?

How about:

class match
{
public:
match( char ch ) : c( ch ) {}
friend istream& operator>>( istream& source, match const& m )
{
if ( source ) {
char ch ;
source >> ch ;
if ( ch != m.c ) {
source.setstate( ios::failbit ) ;
}
}
return source ;
}
private:
char c ;
} ;

istream& operator>>( istream& in, Coordinate& ref )
{
return in >> match( '(' ) >> ref.x
>> match( ',' ) >> ref.y >> match( ')' ) ;
}

It's not transactional. (It may modify ref even if there is an
error.) But neither is yours. It also obeys the standard
conventions for istream (using failbit for formatting errors).
And of course, match is generally usable; if you regularly use
istream to read formatted data, you probably already have it
anyway.

In production code, of course, I'd aim for a transactional
behavior, so the body of the >> operator would look more like:

double x, y ;
if ( in >> match( '(' ) >> x >> match( ',' ) >> y >>
match( ')' ) ) {
ref.x = x ;
ref.y = y ;
}
return in ;

Still no goto:-).

--
James Kanze (GABI Software) mailto:james...@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34

James Kanze

unread,
Mar 27, 2007, 6:53:05 AM3/27/07
to
On Mar 27, 9:22 am, "Edward Rosten" <Edward.Ros...@gmail.com> wrote:

> Perhaps I should have included the full version which will accept (a,
> b) [a b] or just a b, and cleans up properly.

istream&
operator>>( istream& in, ref& out )
{
double x, y ;
in >> ws ;
switch ( in.peek() ) {
case EOF :
in.setstate( ios::failbit ) ;
break ;

case '[' :
in >> match( '[' ) >> x >> y >> match( ']' ) ;
break ;

case '(' :


in >> match( '(' ) >> x >> match( ',' ) >> y >>

match( ')' ) ;
break ;

default :
in >> x >> y ;
break ;
}
if ( in ) {


ref.x = x ;
ref.y = y ;
}
return in ;
}

Still no goto, and I've handled the complete case in about as
many lines as you used for the simplified version.

--
James Kanze (GABI Software) mailto:james...@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34

Francis Glassborow

unread,
Mar 27, 2007, 10:04:55 AM3/27/07
to
{ Quoted signature removed. -mod }

Anand Hariharan wrote:
> Trying to avoid goto just because it is religious is not fruitful.

I would agree.


Of
> course, in C++, one has exceptions and RAII, so the need for goto is
> far less.

However I have never needed to use a goto in C. I am not saying that
goto is useless, just that it has very limited use and when used by a
non-expert it is almost invariably an indicator of poor coding.

It becomes useful in machine generated code exactly because writing
generators that can do design on the fly is a rather hard task :) And as
the code will not be maintained by humans (well not usually) the
problems with readability and maintenance are non-issues.

Daniel T.

unread,
Mar 27, 2007, 10:08:36 AM3/27/07
to
"Edward Rosten" <Edward...@gmail.com> wrote:
> "Kirit Sælensminde" <kirit.saelensmi...@gmail.com> wrote:
>
> > Do you really mean to set badbit on 'is' after successfully parsing?
> > It seems to me that your use of goto has introduced a bug.
>
> The copy/paste bug. I cut off a chunk of the parser which deals with
> other cases, and deleted a "return is" by mistake.

Interestingly enough, this is exactly the kind of problem that Dijkstra
warns about in his paper. You lost one of your textual indexes.

Kirit Sælensminde

unread,
Mar 27, 2007, 12:43:03 PM3/27/07
to
On Mar 27, 5:53 pm, "James Kanze" <james.ka...@gmail.com> wrote:
> switch ( in.peek() ) {
> case EOF :
> in.setstate( ios::failbit ) ;
> break ;
>
> case '[' :
> in >> match( '[' ) >> x >> y >> match( ']' ) ;
> break ;
>
> case '(' :
> in >> match( '(' ) >> x >> match( ',' ) >> y >>
> match( ')' ) ;
> break ;
>
> default :
> in >> x >> y ;
> break ;
> }

Without getting into the whole "is a switch statement really just a
glorified goto", does it not suffer one of the problems of goto, that
being bypassing constructors?

switch ( 1 ) {
std::string str;
case 1: str = "ouch";
}

My impression is that this will bypass the constructor. Am I wrong? (I
really hope that I am).

I did find out somewhere else (I think via Reddit) that Microsoft make
use of goto within MFC. It was always a pretty horrid framework from a
C++ point of view, but I'm sure there's a fair bit of buggy code out
there caused by this sort of issue.


K

Andrei Alexandrescu (See Website For Email)

unread,
Mar 27, 2007, 2:58:10 PM3/27/07
to
James Kanze wrote:
[snip]

> In production code, of course, I'd aim for a transactional
> behavior, so the body of the >> operator would look more like:
>
> double x, y ;
> if ( in >> match( '(' ) >> x >> match( ',' ) >> y >>
> match( ')' ) ) {
> ref.x = x ;
> ref.y = y ;
> }
> return in ;
>
> Still no goto:-).

Well, for my money, using iostreams already puts the code in a low
quality bracket :o).

Andrei

Pete Becker

unread,
Mar 27, 2007, 3:02:38 PM3/27/07
to
Kirit Sælensminde wrote:
>
> Without getting into the whole "is a switch statement really just a
> glorified goto", does it not suffer one of the problems of goto, that
> being bypassing constructors?
>
> switch ( 1 ) {
> std::string str;
> case 1: str = "ouch";
> }
>
> My impression is that this will bypass the constructor. Am I wrong? (I
> really hope that I am).
>

No, you're right. But you're missing the point. goto is bad, switch is
good. So when goto does bad things, that proves you shouldn't use it.
When switch does bad things, you just learn how to avoid them. That's
how dogma works.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

Thant Tessman

unread,
Mar 27, 2007, 3:03:15 PM3/27/07
to
Edward Rosten wrote:

> [...] Jumping out of a nested loop requires a
> goto. [...]

Technically it doesn't if your compiler supports tail-call optimization.
Recursive function calls (even mutually recursive function calls) can,
under certain conditions, be converted by the compiler into loops that
use constant space. From the programmer's point of view, jumping out of
a nested loop is nothing more than returning from a function call.

Some programming languages require tail-call optimization as part of
their standard, but at least some C++ compilers will do it as an
optimization.

-thant

--

James Kanze

unread,
Mar 27, 2007, 3:01:15 PM3/27/07
to
On Mar 27, 6:43 pm, "Kirit Sælensminde" <kirit.saelensmi...@gmail.com>
wrote:

> On Mar 27, 5:53 pm, "James Kanze" <james.ka...@gmail.com> wrote:

> > switch ( in.peek() ) {
> > case EOF :
> > in.setstate( ios::failbit ) ;
> > break ;

> > case '[' :
> > in >> match( '[' ) >> x >> y >> match( ']' ) ;
> > break ;

> > case '(' :
> > in >> match( '(' ) >> x >> match( ',' ) >> y >>
> > match( ')' ) ;
> > break ;

> > default :
> > in >> x >> y ;
> > break ;
> > }

> Without getting into the whole "is a switch statement really just a
> glorified goto", does it not suffer one of the problems of goto, that
> being bypassing constructors?

There's no reason to avoid the question: in C++, the switch
statement is nothing but a glorified goto. The problem isn't
with goto, however, but with the program structures it is used
for; one of the cleanest written programs I ever saw was written
in Fortran IV, and it used goto's all over the place. In C++,
we have real, scoped structures for every necessary flow control
(and some totally unnecessary ones:-)), except a true switch or
case statement. So we use the switch statement we have.

And yes, bypassing constructors can be a problem. In anything
but the most trivial switch case, the actual code for each case
should be wrapped in a {}. And if you forget, the compiler will
tell you.

> switch ( 1 ) {
> std::string str;
> case 1: str = "ouch";
> }

> My impression is that this will bypass the constructor. Am I wrong? (I
> really hope that I am).

No. Such code is illegal, according to the C++ standard, and a
compiler diagnostic is required.

--
James Kanze (GABI Software) mailto:james...@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34

--

Pete Becker

unread,
Mar 27, 2007, 6:36:05 PM3/27/07
to
Pete Becker wrote:
> Kirit Sælensminde wrote:
>>
>> Without getting into the whole "is a switch statement really just a
>> glorified goto", does it not suffer one of the problems of goto, that
>> being bypassing constructors?
>>
>> switch ( 1 ) {
>> std::string str;
>> case 1: str = "ouch";
>> }
>>
>> My impression is that this will bypass the constructor. Am I wrong? (I
>> really hope that I am).
>>
>
> No, you're right.

Whoops, too busy being clever. This would bypass the constructor, so
it's ill-formed.

Walter Bright

unread,
Mar 27, 2007, 6:32:20 PM3/27/07
to
James Kanze wrote:
> I do know of at least
> one compiler (for Modula-2), however, that based itself on the
> explicitly written structures, and didn't even try to optimize
> if there was a goto. According to the authors of the compiler,
> this resulted in much faster optimization, at no cost to typical
> (Modula-2) programs.

And who has written an M2 compiler since 1990? Nobody. Yes, I also knew
of compilers written in the 80's that would abandon all optimizations if
there was a goto. And regardless of the justifications put out by the
authors of such, I'll bet the real answer is they were ignorant of well
known compiler technology. A lot of people did write compilers in the
80's who didn't know anything about it. There's nothing slow about the
loop detection algorithms. I implemented them to run on a friggin' 16
bit DOS computer in 1985.

> Of course, most of the optimizing technology that you would have
> been taught in 1982 was developed for Fortran, where you didn't
> have that luxury.

C'mon, James, even Fortran had structured loops (DO 10 I). Fortran's
heyday was the 60's. The state of the art had long since left Fortran
behind in the 70's. Structured programming was well entrenched by 1982.
Structured programming (i.e. goto-less) was the great buzzword of the 70's.

The buzzword of the 80's was object-oriented programming.
The buzzword of the 90's was generic programming.
The buzzword of the 00's is metaprogramming.
The buzzword of the 10's will be (I predict) concurrent programming.

> One could argue that, today, we could do
> better. Still, it's a tried and true technology, and if I were
> writing a compiler today, I'd probably use it, not because I
> want to support goto particularly well, but because I know it
> works, given the number of compilers which use it.

You'd also use it because it's actually *easier* to write the compiler
that way. It really does pay off to read a book on compiler construction
before expending a large portion of your time implementing one <g>.

Vladimir Marko

unread,
Mar 27, 2007, 6:37:14 PM3/27/07
to
On 26 Mar, 23:13, Walter Bright <wal...@digitalmars-nospamm.com>
wrote:

> Vladimir Marko wrote:
> > On 26 Mar, 13:47, Walter Bright <wal...@digitalmars-nospamm.com>
> > wrote:
> >> I regularly use it, probably more than anyone else I know. If you want
a
> >> sample of it in professional code,
seehttp://ftp.digitalmars.com/dmd.zip

> >> and grep for goto in /dmd/src/dmd/
>
> > That's pure C, isn't it? goto is certainly useful in C, but there are
> > better tools for the job in C++.
>
> It's C++. The front end is in C++ to make it easier to connect with
> existing back ends, which are likely to be in C or C++.

OK, it's C++. But it's easy to miss when having just a quick look.
The files are .c, not .C, .cpp, .cc or .cxx, they start by
including deprecated headers and the classes are introduced by
the keyword "struct" with data members at the beginning. So if one
accidentaly opens say mars.h and inifile.c (with free functions in
global namespace) they can easily miss it.

And when I see a function start by declaring a bunch of local
variables my first assumption is that it must be C. If I find that
in a .d file I just can't help thinking something's gone very
wrong there.

> >> 2) combining block exit cleanup code
> > I thought that's what RAII is for in C++.
>
> Yes, you can do it with RAII, but creating classes for the sole purpose
> of manipulating control flow (rather than storing state) is a
> contortion, not clarification.

First, why should I bother creating classes when I can do it with
a few templates? The only valid complaint here is about C++ not
having proper lambda expression support. For simple things
const scope_exit& dummyName = bind(&Foo::Finish,foo);
should do. Well, anonymous references would help too. And before
you mention scope(success) and scope(failure), the problem in
C++ is not with RAII; it's with the std::uncaught_exception being
insufficient to determine whether to execute the code or not.

Second, creating _objects_ "for the sole purpose of manipulating
control flow" is the very best way of writing exception safe (and
IMO also simple and maintainable) code.

> My favorite solution for this is actually the scope guard
> statement:http://www.digitalmars.com/d/exception-safe.html
> invented by Andrei Alexandrescu and Petru Marginean

Is this not RAII? Is my definition of "resource" much broader
than yours?

> >> 3) combining common error exits
>
> > Ehm, is "goto nomatch;" more readable than "return nomatch;" where
> > nomatch
> > is a local enumerator defined at the _beginning_ of the function
> > (where it
> > nicely documents the return values)?
>
> 6 of one, half dozen of the other.

"goto nomatch;" requires the reader to go down to see if there's
something else than the sole return statement. And I thought you
want to "keep [the code] aesthetically where it belongs". (This
quote from http://www.digitalmars.com/d/exception-safe.html is a
little generalised, originaly it applies only to "unwinding code".)

Regards
Vladimir Marko

Walter Bright

unread,
Mar 27, 2007, 6:33:18 PM3/27/07
to
Gerhard Menzl wrote:
> Walter Bright wrote:
>
>> Yes, you can do it with RAII, but creating classes for the sole
>> purpose of manipulating control flow (rather than storing state) is a
>> contortion, not clarification.
>
> An interesting point of view. Do you also consider replacing
> switch(type) constructs by class hierarchies as a contortion?

Consider this excerpt from the D programming language compiler lexer
that scans for the end of a text line:
---------------------
while (1)
{ unsigned char c = *p;
switch (c)
{
case '\n':
p++;
break;

case '\r':
p++;
if (*p == '\n')
p++;
break;

case 0:
case 0x1A:
break;

default:
if (c & 0x80)
{ unsigned u = decodeUTF();
if (u == PS || u == LS)
break;
}
p++;
continue;
}
break;
}
------------------------
Yeah, I think it would be ridiculous to replace this with a class hierarchy.

--

Walter Bright

unread,
Mar 27, 2007, 6:33:59 PM3/27/07
to
Thant Tessman wrote:
> Edward Rosten wrote:
>
>> [...] Jumping out of a nested loop requires a
>> goto. [...]
>
> Technically it doesn't if your compiler supports tail-call optimization.
> Recursive function calls (even mutually recursive function calls) can,
> under certain conditions, be converted by the compiler into loops that
> use constant space. From the programmer's point of view, jumping out of
> a nested loop is nothing more than returning from a function call.
>
> Some programming languages require tail-call optimization as part of
> their standard, but at least some C++ compilers will do it as an
> optimization.

Tail-call optimization doesn't work if there are RAII objects that need
cleaning up.

Daniel T.

unread,
Mar 27, 2007, 9:03:33 PM3/27/07
to
Pete Becker <pe...@versatilecoding.com> wrote:
> Kirit Sælensminde wrote:
> >
> > Without getting into the whole "is a switch statement really just a
> > glorified goto", does it not suffer one of the problems of goto, that
> > being bypassing constructors?
> >
> > switch ( 1 ) {
> > std::string str;
> > case 1: str = "ouch";
> > }
> >
> > My impression is that this will bypass the constructor. Am I wrong? (I
> > really hope that I am).
> >
>
> No, you're right. But you're missing the point. goto is bad, switch is
> good. So when goto does bad things, that proves you shouldn't use it.
> When switch does bad things, you just learn how to avoid them. That's
> how dogma works.

Dijkstra already covered this issue in his paper:

When we include conditional clauses (if B then A), alternative
clauses (if B then A1 else A2), choice clauses as introduced by C. A.
R. Hoare (case[i] of (A1, A2,···, An)),or conditional expressions as
introduced by J. McCarthy (B1 -> E1, B2 -> E2, ···, Bn -> En), the
fact remains that the progress of the process remains characterized
by a single textual index.

--

Walter Bright

unread,
Mar 27, 2007, 9:02:19 PM3/27/07
to
Vladimir Marko wrote:
> On 26 Mar, 23:13, Walter Bright <wal...@digitalmars-nospamm.com>
> wrote:
> OK, it's C++. But it's easy to miss when having just a quick look.
> The files are .c, not .C, .cpp, .cc or .cxx,

I use C++ as "a better C" <g>.

> they start by including deprecated headers
> and the classes are introduced by the keyword "struct"
> with data members at the beginning.

My personal style.

>>>> 2) combining block exit cleanup code
>>> I thought that's what RAII is for in C++.
>> Yes, you can do it with RAII, but creating classes for the sole purpose
>> of manipulating control flow (rather than storing state) is a
>> contortion, not clarification.
>
> First, why should I bother creating classes when I can do it with
> a few templates? The only valid complaint here is about C++ not
> having proper lambda expression support. For simple things
> const scope_exit& dummyName = bind(&Foo::Finish,foo);
> should do. Well, anonymous references would help too.

I view those complaints as being crippling shortcomings. Setting that
aside for the moment, which do you think is more straightforward:

const scope_exit& dummyName = bind(&Foo::Finish,foo);

or:

scope (exit) foo.Finish();

?

> And before you mention scope(success) and scope(failure),

Too late <g>.

> the problem in
> C++ is not with RAII; it's with the std::uncaught_exception being
> insufficient to determine whether to execute the code or not.

I don't understand.

> Second, creating _objects_ "for the sole purpose of manipulating
> control flow" is the very best way of writing exception safe (and
> IMO also simple and maintainable) code.

This is certainly the conventional wisdom. But the cracks in it are
slowly becoming better known, see
http://www.digitalmars.com/d/exception-safe.html and
http://www.ddj.com/dept/cpp/184403758. The biggest crack is when you
have a sequence of operations that must either all succeed or all fail.
RAII doesn't do well with this, and try-finally is even worse.

>> My favorite solution for this is actually the scope guard
>> statement:http://www.digitalmars.com/d/exception-safe.html
>> invented by Andrei Alexandrescu and Petru Marginean
>
> Is this not RAII? Is my definition of "resource" much broader
> than yours?

It isn't RAII any more than try-finally is RAII. Any RAII, try-finally,
or scope guard construct can be mechanically transformed in to any of
the others. For a simple analogy, any if statement can be transformed
into an equivalent while statement - but that doesn't mean we should do so.

The two articles referenced attempt to explain when it is appropriate to
use each of the 3 techniques. I admit the advantages to scope guard
aren't immediately obvious, until one uses them a few times and then
tries to go back to using RAII or try-finally.


>>>> 3) combining common error exits
>>> Ehm, is "goto nomatch;" more readable than "return nomatch;" where
>>> nomatch
>>> is a local enumerator defined at the _beginning_ of the function
>>> (where it
>>> nicely documents the return values)?
>> 6 of one, half dozen of the other.
>
> "goto nomatch;" requires the reader to go down to see if there's
> something else than the sole return statement.

The single-entry, single-exit paradigm has value, too.

Keith H Duggar

unread,
Mar 27, 2007, 11:35:00 PM3/27/07
to
Francis Glassborow wrote:
> Of course the above are my (strongly held) opinions but I would dearly
> like to see a single real example. Every goto I have ever encountered
> disappears when the code is redesigned to be simpler, more readable and
> more maintainable.

Consider Yevgeni Kuzmin's efficient cicrle-drawing algorithm (this
version below evaluates f on a raidus r octant centered at (0,0)):

template < class F > inline
void circle_octant ( int r, F f )
{
int x = r ;
int y = 0 ;
int e = -r / 2 ;

if ( r & 1 ) --e , goto odd ;

even :
f(x,y) ;
if ( y >= x ) return ;
e += y++ ;
if ( e >= 0 ) e -= --x ;
odd :
f(x,y) ;
if ( y >= x ) return ;
e += ++y ;
if ( e >= 0 ) e -= --x ;
goto even ;
}

Note there may be an error or two. I couldn't locate the full paper
on my current harddrive. But I think the above is correct.

Care to make the above "simpler, more readable and more maintainable"?

Keith

Michael K. O'Neill

unread,
Mar 28, 2007, 2:09:08 AM3/28/07
to
"James Kanze" <james...@gmail.com> wrote in message
news:1175014084.8...@y66g2000hsf.googlegroups.com...

> On Mar 27, 6:43 pm, "Kirit Sælensminde" <kirit.saelensmi...@gmail.com>
wrote
> >
> >
> > < snip >

> >
> >
> > Without getting into the whole "is a switch statement really just a
> > glorified goto", does it not suffer one of the problems of goto, that
> > being bypassing constructors?
>
> There's no reason to avoid the question: in C++, the switch
> statement is nothing but a glorified goto. The problem isn't
> with goto, however, but with the program structures it is used
> for; one of the cleanest written programs I ever saw was written
> in Fortran IV, and it used goto's all over the place. In C++,
> we have real, scoped structures for every necessary flow control
> (and some totally unnecessary ones:-)), except a true switch or
> case statement. So we use the switch statement we have.
>
>
> < snip >

It's difficult to see any principled, moral distinction between an "evil"
goto and supposedly "acceptable" constructs like break or continue, or even
an early return.

With an appropriate level of sarcasm, Pete Becker (below) seems to correctly
characterize the "goto" debate as a debate over dogma: goto is "bad" and
other constructs are "good", so when goto does bad things, that proves you
shouldn't use goto, whereas when other constructs do bad things, that only
proves that you have not yet learned how to use them correctly.

Of course the real answer is that any programming technique can be used
poorly, but that does not make them inherently evil/bad. Yes, Dijkstra
showed us that you can re-write code to be goto-free, but that doesn't
necessarily make the code better or clearer. In fact, the re-write often
requires the introduction of condition variables that are logically
unrelated and distinct from the algorithm being implemented.

The battle over goto has been waged for many years, beginning perhaps with
Edsger W. Dijkstra's seminal "Letter" to the ACM in 1968: "Go To Statement
Considered Harmful", Communications of the ACM, Vol. 11, No. 3, March 1968,
pp. 147-148. The Letter can be found all over the Internet; one URL is
http://www.acm.org/classics/oct95/ .

Less known is the marvelously-titled (but somewhat ill-tempered) response
written by Rubin around 20 years after Dijkstra's original article. It also
was published in the "Letters" to the ACM: Rubin, Frank, "'GOTO Considered
Harmful' Considered Harmful" (letter to the editor), Communications of the
ACM, vol. 30, no. 3 (March 1987), pp. 195-6. I had trouble finding that one
on the web, but one URL is
http://paramount.www.ecn.purdue.edu/ParaMount/papers/rubin87goto.pdf .
Here's a nice quote from Rubin's response, which gives a taste of his
viewpoint:

"...[T]he notion that GOTO is harmful is accepted almost universally,
without question or doubt. To many people, 'structured programming' and
'GOTO-less programming' have become synonymous. This has caused
incalculable harm to the field of programming, which has lost an efficacious
tool. It is like butchers banning knives because workers sometimes cut
themselves. Programmers must devise elaborate workarounds, use extra flags,
nest statements excessively, or use gratuitous subroutines. The result is
that GOTO-less programs are harder and costlier to create, test, and modify.
..."

Best regards,
Mike

Alf P. Steinbach

unread,
Mar 28, 2007, 4:14:28 AM3/28/07
to
* Keith H Duggar:

The only difference in the even and odd cases is that 'e' is 1 larger in
the odd case. And this essentially boolean value is represented by the
execution position. Represent it as a variable instead.

template< class F >
void circle_octant( int r, F f )


{
int x = r;
int y = 0;
int e = -r/2;

bool oddStep = !!( r & 1 );

e -= oddStep;
for( ;; )
{
f( x,y );
if( y >= x ) { return ; }
e += y + oddStep;
++y;
oddStep = !oddStep;
if( e >= 0 ) { --x; e -= x; }
}
}

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Walter Bright

unread,
Mar 28, 2007, 4:17:55 AM3/28/07
to
Michael K. O'Neill wrote:
> It's difficult to see any principled, moral distinction between an "evil"
> goto and supposedly "acceptable" constructs like break or continue, or even
> an early return.

The one technical issue is that one can use goto to create what is
called an "irreducible flow graph", or in other words, a loop with
multiple entry points. It is impossible to create such with structured code.

Some optimization techniques fail with irreducible flow graphs, but this
is mitigated by:

1) irreducible flow graphs are easy to detect
2) irreducible flow graphs are very rare even in the worst spaghetti code
3) ergo, it's practical to just skip doing some optimizations on
irreducible flow graphs
4) techniques exist to transform irreducible flow graphs into reducible ones

A corollary of this is that people like me who use goto often, but don't
create irreducible flow graphs, find the palette of common structured
coding constructs to be insufficient.

To address many of the common uses for gotos, the D programming language
extends the usual C++ structured coding constructs with multilevel
breaks and scope guard.

Gerhard Menzl

unread,
Mar 28, 2007, 5:28:52 AM3/28/07
to
Walter Bright wrote:

Maybe my wording was too terse. I was not talking about replacing just
about *any* switch statement by a class hierarchy, but switches on
*type*: if it's this type, do this, if it's that type, do that, etc. The
textbook OO solution for this sort of thing is to use runtime
polymorphism (in C++ virtual functions). Yet this seems to fit your
description of "creating classes for the sole purpose of manipulating
control flow", so that made me wonder whether you regard OO programming
by and large as a contortion.

--
Gerhard Menzl

Non-spammers may respond to my email address, which is composed of my
full name, separated by a dot, followed by at, followed by "fwz",
followed by a dot, followed by "aero".

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Kanze

unread,
Mar 28, 2007, 5:45:41 AM3/28/07
to
On Mar 28, 12:32 am, Walter Bright <wal...@digitalmars-nospamm.com>
wrote:

> James Kanze wrote:
> > I do know of at least
> > one compiler (for Modula-2), however, that based itself on the
> > explicitly written structures, and didn't even try to optimize
> > if there was a goto. According to the authors of the compiler,
> > this resulted in much faster optimization, at no cost to typical
> > (Modula-2) programs.

> And who has written an M2 compiler since 1990? Nobody. Yes, I also knew
> of compilers written in the 80's that would abandon all optimizations if
> there was a goto. And regardless of the justifications put out by the
> authors of such, I'll bet the real answer is they were ignorant of well
> known compiler technology.

The authors happened to be some of the top experts in
optimization around (and the compiler did optimize more than
most other compilers at the time). Be careful about speculating
about cases you apparently aren't familiar with.

> A lot of people did write compilers in the
> 80's who didn't know anything about it. There's nothing slow about the
> loop detection algorithms. I implemented them to run on a friggin' 16
> bit DOS computer in 1985.

The compiler in question optimized a good deel better than the
Zortech compilers I used at about the same time.

> > Of course, most of the optimizing technology that you would have
> > been taught in 1982 was developed for Fortran, where you didn't
> > have that luxury.

> C'mon, James, even Fortran had structured loops (DO 10 I).

Obviously, we have a different definition of "structured".

> Fortran's
> heyday was the 60's. The state of the art had long since left Fortran
> behind in the 70's.

Even in the 1980's, Fortran dominated in numeric processing (the
one field where optimization is really important). All of the
work I'm aware of in automatic parallelization (Ted Kennedy, at
Rice University) was done for Fortran. Even well into the
1990's, if you wanted good optimization, you used Fortran,
because the compilers for other languages weren't up to the same
level.

> Structured programming was well entrenched by 1982.
> Structured programming (i.e. goto-less) was the great buzzword of the 70's.

In the 1970's, it was the buzzword. It the 1980's, people
actually started using it:-).

> The buzzword of the 80's was object-oriented programming.
> The buzzword of the 90's was generic programming.
> The buzzword of the 00's is metaprogramming.
> The buzzword of the 10's will be (I predict) concurrent programming.

And of course, actual use doesn't really come until the
following decade.

The buzzword also depends on the milieu. During the late
1980's, I was working along side of people involved in numeric
processing, and the buzzword among them at the time was
concurrent processing, particularly, the automated use of array
processors.

> > One could argue that, today, we could do
> > better. Still, it's a tried and true technology, and if I were
> > writing a compiler today, I'd probably use it, not because I
> > want to support goto particularly well, but because I know it
> > works, given the number of compilers which use it.

> You'd also use it because it's actually *easier* to write the compiler
> that way. It really does pay off to read a book on compiler construction
> before expending a large portion of your time implementing one <g>.

I've already implemented several, thank you. And I'm well aware
of the literature on the subject, and the trade offs involved.

--
James Kanze (GABI Software) mailto:james...@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34

Walter Bright

unread,
Mar 28, 2007, 9:24:33 AM3/28/07
to
James Kanze wrote:
> On Mar 28, 12:32 am, Walter Bright <wal...@digitalmars-nospamm.com>
> wrote:
>> James Kanze wrote:
>>> I do know of at least
>>> one compiler (for Modula-2), however, that based itself on the
>>> explicitly written structures, and didn't even try to optimize
>>> if there was a goto. According to the authors of the compiler,
>>> this resulted in much faster optimization, at no cost to typical
>>> (Modula-2) programs.
>
>> And who has written an M2 compiler since 1990? Nobody. Yes, I also knew
>> of compilers written in the 80's that would abandon all optimizations if
>> there was a goto. And regardless of the justifications put out by the
>> authors of such, I'll bet the real answer is they were ignorant of well
>> known compiler technology.
>
> The authors happened to be some of the top experts in
> optimization around (and the compiler did optimize more than
> most other compilers at the time). Be careful about speculating
> about cases you apparently aren't familiar with.

But I have written optimizers that worked with gotos, and I know for a
fact that they do not cost significant runtime speed. Constructing the
flow graph doesn't even register on the performance profile. There's no
reason not to use them (except that they take longer to implement), so I
remain skeptical of unknown compiler experts with unverifiable claims.

> The compiler in question optimized a good deel better than the
> Zortech compilers I used at about the same time.

M2 is a much simpler language, and still they threw in the towel in the
presence of a goto. It's easier to generate better code if one
constrains the semantics. M2 doesn't have complications like arbitrary
pointers, aliases, and constants that can't be relied on to be constant,
all of which hinder good code generation.

In contrast, and perhaps counterintuitively, it takes a lot of work to
generate decent code for C and C++.

FWIW, I wrote the entire C++ compiler - front end, optimizer, code
generator, and runtime library. Just doing the C++ front end consumed
the vast majority of my time. If I was able to work full time on the
optimizer, there's a lot of improvements I could have made. Tossing out
the DFO-based optimizations wouldn't have improved anything. I regret I
wasn't able to spend more time on the optimizer, as that was the really
fun part.

I'm not aware of any optimization you can make without gotos that you
can with. If you know of any, please post.

> Even in the 1980's, Fortran dominated in numeric processing (the
> one field where optimization is really important). All of the
> work I'm aware of in automatic parallelization (Ted Kennedy, at
> Rice University) was done for Fortran. Even well into the
> 1990's, if you wanted good optimization, you used Fortran,
> because the compilers for other languages weren't up to the same
> level.

Fortran's semantics gave it a fundamental advantage in loop optimization
- arrays without aliases. It doesn't matter how advanced a C++ optimizer
is, it can't generate as good code because of the aliasing semantics.
That has nothing to do with optimizing with/without goto's.

> I've already implemented several, thank you. And I'm well aware
> of the literature on the subject, and the trade offs involved.

Have you implemented one from the ground up that constructed DFO graphs
and did DFA operations on it? What kind of DFA based optimizations did
you do? Where did a profiler say the most time was consumed?

Daniel T.

unread,
Mar 28, 2007, 12:28:35 PM3/28/07
to
"Michael K. O'Neill" <MikeAT...@nospam.hotmail.com> wrote:

> "James Kanze" <james...@gmail.com> wrote:
> > "Kirit Sælensminde" <kirit.saelensmi...@gmail.com> wrote
> > >
> > >
> > > < snip >
> > >
> > >
> > > Without getting into the whole "is a switch statement really just a
> > > glorified goto", does it not suffer one of the problems of goto, that
> > > being bypassing constructors?
> >
> > There's no reason to avoid the question: in C++, the switch
> > statement is nothing but a glorified goto. The problem isn't
> > with goto, however, but with the program structures it is used
> > for; one of the cleanest written programs I ever saw was written
> > in Fortran IV, and it used goto's all over the place. In C++,
> > we have real, scoped structures for every necessary flow control
> > (and some totally unnecessary ones:-)), except a true switch or
> > case statement. So we use the switch statement we have.
> >
> >
> > < snip >
>
> It's difficult to see any principled, moral distinction between an "evil"
> goto and supposedly "acceptable" constructs like break or continue, or
even
> an early return.

So many people over the years have heard that "goto is harmful" and
then, without asking why, have looked for reasons. They end up with a
bunch of excuses like "goto can bypass constructors" which have nothing
to do with Dijkstra's argument.

> Less known is the marvelously-titled (but somewhat ill-tempered) response
> written by Rubin around 20 years after Dijkstra's original article. It
also
> was published in the "Letters" to the ACM: Rubin, Frank, "'GOTO Considered
> Harmful' Considered Harmful" (letter to the editor), Communications of the
> ACM, vol. 30, no. 3 (March 1987), pp. 195-6. I had trouble finding that
one
> on the web, but one URL is
> http://paramount.www.ecn.purdue.edu/ParaMount/papers/rubin87goto.pdf .
> Here's a nice quote from Rubin's response, which gives a taste of his
> viewpoint:
>
> "...[T]he notion that GOTO is harmful is accepted almost universally,
> without question or doubt. To many people, 'structured programming' and
> 'GOTO-less programming' have become synonymous. This has caused
> incalculable harm to the field of programming, which has lost an
efficacious
> tool. It is like butchers banning knives because workers sometimes cut
> themselves. Programmers must devise elaborate workarounds, use extra
flags,
> nest statements excessively, or use gratuitous subroutines. The result is
> that GOTO-less programs are harder and costlier to create, test, and
modify.
> ..."

In the letter above Rubin presents two examples often cited whenever the
subject comes up and says that because the program fragments he presents
as solutions have fewer lines of code, fewer operators, and fewer tokens
if goto is used, they are better. "More importantly, the programmers who
used gotos took less time to arrive at their solutions." says he. That
last bit is especially egregious because safer solutions tend to take
more time to create than dangerous solutions, so it is more an
inditement of goto than a support of it. The letter makes no attempt to
show any flaw in Dijkstra's argument.

Thant Tessman

unread,
Mar 28, 2007, 12:29:56 PM3/28/07
to
Walter Bright wrote:
> Thant Tessman wrote:
>> Edward Rosten wrote:
>>
>>> [...] Jumping out of a nested loop requires a
>>> goto. [...]
>>
>> Technically it doesn't if your compiler supports tail-call
>> optimization. Recursive function calls (even mutually recursive
>> function calls) can, under certain conditions, be converted by the
>> compiler into loops that use constant space. From the programmer's
>> point of view, jumping out of a nested loop is nothing more than
>> returning from a function call.
>>
>> Some programming languages require tail-call optimization as part of
>> their standard, but at least some C++ compilers will do it as an
>> optimization.
>
> Tail-call optimization doesn't work if there are RAII objects that need
> cleaning up.

Why? Is this because the compiler has to promise to clean up stuff in
the same order it would if the stack were preserved?

Regardless, my assumption when replying was that someone might be
tempted to use goto in the case of nested loops to avoid the performance
cost of other flow constructs. In this situation it's probably not a
good idea to be littering the insides of your loops with RAII objects.
(And for what it's worth, RAII seems particular to the C++ family of
languages.)

-thant

Francis Glassborow

unread,
Mar 28, 2007, 12:32:45 PM3/28/07
to
In article <0MmdnUoEhPPD3pfb...@comcast.com>, Walter Bright
<wal...@digitalmars-nospamm.com> writes

>I'm not aware of any optimization you can make without gotos that you
>can with. If you know of any, please post.
I think you meant:

I am not aware of any optimisation you can make without gotos that you
*cannot* make with them.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects

Thant Tessman

unread,
Mar 28, 2007, 3:11:26 PM3/28/07
to
Zeljko Vrba wrote:

[...]

> Yes, the simplest example is to bail out of nested loops:
>
> while(a) {
> while(b) {
> if(something)
> goto out_a; // exit the outer loop
> }
> // more code
> }
> out_a: // rest of the program
>
> Try to rewrite the above code without using goto.


inline void f(A a, B b) {
while (a) {
while (b) {
if (something) return;
}
// more code
}
}


int main() {

// some of program

f(a, b);

// rest of program
}

If the f function requires more state information from the surrounding
scope, then pass it in.

Since BASIC I've only used goto once. It was to get around a bug in an
implementation of lex.

-thant

--

Zeljko Vrba

unread,
Mar 28, 2007, 10:51:36 PM3/28/07
to
On 2007-03-28, Thant Tessman <a...@standarddeviance.com> wrote:
>
> inline void f(A a, B b) {
> while (a) {
> while (b) {
> if (something) return;
> }
> // more code
> }
> }
>
The banning of goto was to promote "structured programming". In that line,
structured programming has had another principle that people have, it seems,
mostly forgotten: every function should have one entry and one exit. The
above code clearly violates that principle. So, if one is to be consistent,
one should be consistent all the way through.

Not to mention that I extremely dislike this suggestion - it chops up into
several parts the code what once has been a single function. Btw, your code
seems to have a blatant error: the function should have been declared as

inline void f(A &a, B &b)

[note the references].

Walter Bright

unread,
Mar 28, 2007, 10:52:49 PM3/28/07
to
Francis Glassborow wrote:
> In article <0MmdnUoEhPPD3pfb...@comcast.com>, Walter Bright
> <wal...@digitalmars-nospamm.com> writes
>> I'm not aware of any optimization you can make without gotos that you
>> can with. If you know of any, please post.
> I think you meant:
>
> I am not aware of any optimisation you can make without gotos that you
> *cannot* make with them.

Right. Thanks for the correction.

--

Walter Bright

unread,
Mar 28, 2007, 10:56:32 PM3/28/07
to
Thant Tessman wrote:

> Walter Bright wrote:
>> Tail-call optimization doesn't work if there are RAII objects that
>> need cleaning up.
>
> Why? Is this because the compiler has to promise to clean up stuff in
> the same order it would if the stack were preserved?

Yes. Tail call optimization requires that the function call must be the
very last thing the function does. With RAII objects, the cleanup is last.

> Regardless, my assumption when replying was that someone might be
> tempted to use goto in the case of nested loops to avoid the performance
> cost of other flow constructs. In this situation it's probably not a
> good idea to be littering the insides of your loops with RAII objects.

Due to the nature of C++ programming, you can easily wind up with RAII
objects without realizing it.

Andrei Alexandrescu (See Website For Email)

unread,
Mar 28, 2007, 10:57:02 PM3/28/07
to
Thant Tessman wrote:
> Zeljko Vrba wrote:
>
> [...]
>
>> Yes, the simplest example is to bail out of nested loops:
>>
>> while(a) {
>> while(b) {
>> if(something)
>> goto out_a; // exit the outer loop
>> }
>> // more code
>> }
>> out_a: // rest of the program
>>
>> Try to rewrite the above code without using goto.
>
>
> inline void f(A a, B b) {
> while (a) {
> while (b) {
> if (something) return;
> }
> // more code
> }
> }
>
>
> int main() {
>
> // some of program
>
> f(a, b);
>
> // rest of program
> }
>
> If the f function requires more state information from the surrounding
> scope, then pass it in.

This reeks much of the same smell as the (now, I hope, hackneyed)
recommendation to make loops into classes just to use for_each with them.

> Since BASIC I've only used goto once. It was to get around a bug in an
> implementation of lex.

I don't use it much either, but I guess I'm not claiming this makes me a
better person :o).


Andrei

Vladimir Marko

unread,
Mar 28, 2007, 10:53:44 PM3/28/07
to
On 28 Mar, 02:02, Walter Bright <wal...@digitalmars-nospamm.com>
wrote:

> Vladimir Marko wrote:
> > On 26 Mar, 23:13, Walter Bright <wal...@digitalmars-nospamm.com>
> > wrote:
> > ... For simple things

> > const scope_exit& dummyName = bind(&Foo::Finish,foo);
> > should do. Well, anonymous references would help too.
>
> I view those complaints as being crippling shortcomings. Setting that
> aside for the moment, which do you think is more straightforward:
>
> const scope_exit& dummyName = bind(&Foo::Finish,foo);
>
> or:
>
> scope (exit) foo.Finish();
>
> ?

I'd prefer
SCOPE(exit) foo.Finish;
where SCOPE is a properly defined macro -- I'm not calling
foo.Finish() now, I'm just scheduling the function object for
delayed invocation. Unfortunately, closures cannot be formed
as object.member_function in C++.

> > And before you mention scope(success) and scope(failure),
>
> Too late <g>.
>
> > the problem in
> > C++ is not with RAII; it's with the std::uncaught_exception being
> > insufficient to determine whether to execute the code or not.
>
> I don't understand.

A naive implementation of scope(failure) is
const scope_exit& dummy = boost::lambda::if_then(
&std::uncaught_exception,
failure_functor);
The problem is that std::uncaught_exception() might return true
if examined while constructing the scope_exit object and then it
will be true even if we exit the scope without throwing. Example:

struct Evil{
~Evil()
try
{
const scope_exit& dummy = boost::lambda::if_then(
&std::uncaught_exception,
&undo);
throwing_function();
}
catch(...) { }
};

If an Evil object is being destroyed during stack unwinding,
undo will be called regardless of whether throwing_function
throws or not.

> > Second, creating _objects_ "for the sole purpose of manipulating
> > control flow" is the very best way of writing exception safe (and
> > IMO also simple and maintainable) code.
>
> This is certainly the conventional wisdom. But the cracks in it are

> slowly becoming better known, seehttp://www.digitalmars.com/d/exception-safe.htmlandhttp://www.ddj.com/dept/cpp/184403758. The biggest crack is when you


> have a sequence of operations that must either all succeed or all fail.
> RAII doesn't do well with this, and try-finally is even worse.

I can see many deficiencies of C++ that make RAII more complicated
than it has to be but I fail to see the cracks in RAII itself.

> >> My favorite solution for this is actually the scope guard
> >> statement:http://www.digitalmars.com/d/exception-safe.html
> >> invented by Andrei Alexandrescu and Petru Marginean
>
> > Is this not RAII? Is my definition of "resource" much broader
> > than yours?
>
> It isn't RAII any more than try-finally is RAII.

Apparently, you didn't get my point. Every single ScopeGuard takes
ownership of "resources" allocated for some kind of "transaction".
Thus, ScopeGuard is a RAII tool by definition. My definition.

> >>>> 3) combining common error exits
>

> > "goto nomatch;" requires the reader to go down to see if there's
> > something else than the sole return statement.
>
> The single-entry, single-exit paradigm has value, too.

I'm no fan of SESE. It's always been PITA when I used it.
IMO, with goto you pretend to use the SESE while actually
having multiple returns.

Regards
Vladimir Marko

Daniel T.

unread,
Mar 28, 2007, 10:56:53 PM3/28/07
to
Walter Bright <wal...@digitalmars-nospamm.com> wrote:

> For example:
>
> while(a) {
> while(b) {
> if(foo())


> goto out_a; // exit the outer loop
> }
> // more code
> }
> out_a:
> // rest of the program
>

> becomes:
>
> while(true){
> bool tmp = false;
> while(b && !(tmp = (foo() != 0))){
> // code which might change the
> // truth value of something
> }
> if(tmp or not a) break;
> // more code


> }
> // rest of the program
>

> I have to look at that pretty carefully to see if it really is the same
> as the simple goto version.

The two examples are not the same and that is the point. The former
(goto) example requires more context to understand than the latter. That
is the point Dijkstra makes in the article and one no one has even
attempted to refute in this thread.

For example, put your finger at the point where the comment "rest of the
program" is and ask yourself what code was executed before that point.
In the latter example, one need only know what the value of tmp, b, and
a are (or would be if it still existed in the case of tmp,) in order to
know exactly what has transpired. In the former case you cannot
reconstitute the execution path. Maybe foo() returned true, maybe the
loop naturally fell out, or maybe the entire while loop was skipped due
to some other goto above it that went to the out_a label. In using the
goto, you have lost the "progress of the process" as Dijkstra points out
in his paper.

Tony Delroy

unread,
Mar 28, 2007, 11:01:52 PM3/28/07
to
On Mar 26, 11:58 pm, Francis Glassborow
<franc...@robinton.demon.co.uk> wrote:
> [I] wrote:
> > It may be both faster and more maintainable to use a goto [ to break
> > out of nested for/while loops ].
> Any speed advantage is minuscule (well it might be faster for a naive
> programmer to 'design' and write the resulting code?). However, nested
> loops, conditionals etc. are almost always a maintenance nightmare and I
> do not see how using goto would reduce that.

Sorry, but it's simply irresponsible to presume the speed advantage is
miniscule. Sure premature optimisation is generally evil, but that
doesn't mean
real optimisation issues shouldn't be discussed. On occasions,
CPU-intensive algorithms are run with deeply nested loops, and
depending on calculations in the inner loops, you may want - for
instance - to quickly abandon a branch and recommence at some other
level. These situations are very rare for most programmers (as
they're only common in a few problem domains), but when they do exist
the speed advantages are definitely not miniscule. Naive programmers
aren't likely to be working on such algorithms.

And there's nothing inherently ugly or ill-designed about the use of
gotos in such situations. Like any code, we can't make it simpler
than the problem we're trying to solve, and where goto fits the way we
should think about the issue it may be a better fit than convoluted
for/while loops accumulating myriad hideously complicated exit
conditions. It may also be better than abusing exceptions.

> > - in case statements, you sometimes have multiple cases that need
> > trivial initial processing, but then do the same processing as some
other
> > label.
> In 25 years of programming in C and over 15 of doing so in C++ I cannot
> recall a single time when I would have wanted to do that.

And yet Walter mentions the exact same usage for the exact same
reasons. 25 years working in the same problem domains and application
levels won't give you broad experience. I find the kind of code where
gotos sometimes seem the optimal fit include low-level parsing/lexing
routines, language grammar analysis, state machines, and expression
parsing. I gather from his reply that Walter does to. And it may
interest you that despite the lack of need in 15 years of C++
experience, and general dislike you show for gotos, a through boost
turned up 189 gotos in four files
from three libraries. Yet the C++ community in general seems to
worship boost as a shining light of code quality - much of the praise
being in my opinion well deserved.

> > - there are some famous optimisations for efficient data copying that
> > rely on gotos to jump into a contiguous set of operation code at a
> > position that ensures the right number of iterations are run
> > probably a few others I can't think of off the top of my head...
>
> Yes, and though such things are amusing, they also have no place in
> modern code.

Quite simply wrong. Of course, the example I alluded to is Duff's
device (see http://en.wikipedia.org/wiki/Duff's_device).
Interestingly, Wikipedia says Stroustrup gives a similar example in TC
+
+PL, but even though it's right beside me I'm not interested enough to
look. I guess you think he's a naive programmer too ;-) ?

> Of course the above are my (strongly held) opinions but I would dearly
> like to see a single real example. Every goto I have ever encountered
> disappears when the code is redesigned to be simpler, more readable and
> more maintainable.

Please look at boost and Duff's Device, and if they're not enough, get
back to me.

Regards,

Tony

Walter Bright

unread,
Mar 29, 2007, 1:24:54 AM3/29/07
to
Daniel T. wrote:

> Walter Bright <wal...@digitalmars-nospamm.com> wrote:
>> I have to look at that pretty carefully to see if it really is the same
>> as the simple goto version.
> The two examples are not the same and that is the point. The former
> (goto) example requires more context to understand than the latter. That
> is the point Dijkstra makes in the article and one no one has even
> attempted to refute in this thread.

I see the same issue (the examples are logically different) and come to
the opposite conclusion!

> For example, put your finger at the point where the comment "rest of the
> program" is and ask yourself what code was executed before that point.
> In the latter example, one need only know what the value of tmp, b, and
> a are (or would be if it still existed in the case of tmp,) in order to
> know exactly what has transpired. In the former case you cannot
> reconstitute the execution path. Maybe foo() returned true, maybe the
> loop naturally fell out, or maybe the entire while loop was skipped due
> to some other goto above it that went to the out_a label. In using the
> goto, you have lost the "progress of the process" as Dijkstra points out
> in his paper.

Yet I see the problem as I failed to grasp the goto-less logic. I
understood the goto one perfectly.

Sushrut Sardeshmukh

unread,
Mar 29, 2007, 1:24:55 AM3/29/07
to
On Mar 27, 8:06 am, "Anand Hariharan"
<mailto.anand.hariha...@gmail.com> wrote:
> On Mar 26, 2:51 am, "Sushrut Sardeshmukh" <bestbr...@gmail.com> wrote:
> (...)
>
> > 1. Is it really so bad to use goto? Does any one supports / use it?
> > 2. If goto is so bad, then why C++ still supports it? May be to
> > maintain compatibility with 'C'. In that case, compiler should give
> > out a warning, right?
> > 3. For every place where goto was used, there were better ways to plan
> > the code in the code base I discussed above. But ......is there any
> > situation where goto is must?
>
> If your project is entirely in C, use of goto is unavoidable IMHO.
> One would typically find code like so:
>
> void Func(void)
> {
> /* Declare all your pointers at the very top, and initialise to NULL
> right at beginning */
>
> /* Initialise Return Code to Failure */
>
> /* Keep checking for return codes of every function you call. Persist
> with other checks (e.g., invariants). If something fails, set Func's
> return code and jump to "CleanUp_Label" */
>
> /* Set Return Code to Success */
> CleanUp_Label:
>
> /* For each pointer that represents a resource, if pointer not NULL,
> release resource corresponding to pointer */
>
> }
>
> Trying to avoid goto just because it is religious is not fruitful. Of
> course, in C++, one has exceptions and RAII, so the need for goto is
> far less.

Thats exactly the type of code that i encountered with.
but why not code it like this..
int foo(some arguments)
{
myclass * ptr1 = NULL;
//do something with ptr1
if ( ptr1->somefunction())
{
goto Found_Error_free_pointer_return_errCode;
}
//compare it with below
if ( ptr1->somefunction())
{
return found_Error_free_pointer_return_errCode();
}
}

Now question is
How useful it is to replace goto labeled code with a function?
Does it make my code better?

Walter Bright

unread,
Mar 29, 2007, 1:22:32 AM3/29/07
to
Vladimir Marko wrote:
> On 28 Mar, 02:02, Walter Bright <wal...@digitalmars-nospamm.com>
> wrote:
>> Vladimir Marko wrote:
>>> On 26 Mar, 23:13, Walter Bright <wal...@digitalmars-nospamm.com>
>>> wrote:
>>> ... For simple things
>>> const scope_exit& dummyName = bind(&Foo::Finish,foo);
>>> should do. Well, anonymous references would help too.
>> I view those complaints as being crippling shortcomings. Setting that
>> aside for the moment, which do you think is more straightforward:
>>
>> const scope_exit& dummyName = bind(&Foo::Finish,foo);
>>
>> or:
>>
>> scope (exit) foo.Finish();
>>
>> ?
>
> I'd prefer
> SCOPE(exit) foo.Finish;
> where SCOPE is a properly defined macro -- I'm not calling
> foo.Finish() now, I'm just scheduling the function object for
> delayed invocation. Unfortunately, closures cannot be formed
> as object.member_function in C++.

Right - it doesn't work in C++. And if you find you have to use macros
to invent syntactical constructs, well, those kind of things always make
me uneasy.

>>> And before you mention scope(success) and scope(failure),
>> Too late <g>.
>>
>>> the problem in
>>> C++ is not with RAII; it's with the std::uncaught_exception being
>>> insufficient to determine whether to execute the code or not.
>> I don't understand.
>
> A naive implementation of scope(failure) is
> const scope_exit& dummy = boost::lambda::if_then(
> &std::uncaught_exception,
> failure_functor);
> The problem is that std::uncaught_exception() might return true
> if examined while constructing the scope_exit object and then it
> will be true even if we exit the scope without throwing. Example:
>
> struct Evil{
> ~Evil()
> try
> {
> const scope_exit& dummy = boost::lambda::if_then(
> &std::uncaught_exception,
> &undo);
> throwing_function();
> }
> catch(...) { }
> };
>
> If an Evil object is being destroyed during stack unwinding,
> undo will be called regardless of whether throwing_function
> throws or not.

Fortunately, scope(success) and scope(failure) are easily and robustly
implementable using try-catch-finally:

scope(failure) s;

=> try { ... } catch (o) { s; throw o; }

scope(success) s;

=> int x=0; try { ... } catch (o) { x = 1; throw o; } finally { if (!x) s; }

>>> Second, creating _objects_ "for the sole purpose of manipulating
>>> control flow" is the very best way of writing exception safe (and
>>> IMO also simple and maintainable) code.
>> This is certainly the conventional wisdom. But the cracks in it are
>> slowly becoming better known, seehttp://www.digitalmars.com/d/exception-safe.htmlandhttp://www.ddj.com/dept/cpp/184403758. The biggest crack is when you
>> have a sequence of operations that must either all succeed or all fail.
>> RAII doesn't do well with this, and try-finally is even worse.
>
> I can see many deficiencies of C++ that make RAII more complicated
> than it has to be but I fail to see the cracks in RAII itself.

If you're willing to accept the necessarily contorted method and
crippling deficiencies of doing scope guards in C++, I agree you can get
the job done that way.


>>>> My favorite solution for this is actually the scope guard
>>>> statement:http://www.digitalmars.com/d/exception-safe.html
>>>> invented by Andrei Alexandrescu and Petru Marginean
>>> Is this not RAII? Is my definition of "resource" much broader
>>> than yours?
>> It isn't RAII any more than try-finally is RAII.
>
> Apparently, you didn't get my point. Every single ScopeGuard takes
> ownership of "resources" allocated for some kind of "transaction".
> Thus, ScopeGuard is a RAII tool by definition. My definition.

You're right, I didn't get your point. But I don't agree with your
definition because it tries to redefine the problem in a way that
doesn't help.

BTW, the scope guard statement is implemented internally in the compiler
by transforming it into a combination of try-catch-finally statements.
So are RAII objects.

> I'm no fan of SESE. It's always been PITA when I used it.
> IMO, with goto you pretend to use the SESE while actually
> having multiple returns.

You could look at it that way. But there is another, subtler reason I do
it. With most CPUs, faster code is the branch not taken. So I'll use
gotos to get the uncommon cases out of the direct control flow.
Sometimes the result isn't the prettiest, but when you feel the need for
speed..

Thant Tessman

unread,
Mar 29, 2007, 3:25:24 AM3/29/07
to
Walter Bright wrote:

[...]

> Due to the nature of C++ programming, you can easily wind up with RAII
> objects without realizing it.

Maybe this says more about RAII than it does about goto.

-thant

Thant Tessman

unread,
Mar 29, 2007, 3:25:22 AM3/29/07
to
Zeljko Vrba wrote:
> On 2007-03-28, Thant Tessman <a...@standarddeviance.com> wrote:
>> inline void f(A a, B b) {
>> while (a) {
>> while (b) {
>> if (something) return;
>> }
>> // more code
>> }
>> }
>>
> The banning of goto was to promote "structured programming". In that line,
> structured programming has had another principle that people have, it seems,
> mostly forgotten: every function should have one entry and one exit. [...]

http://preview.tinyurl.com/3yjg7m

Goto is bad because it make it harder to reason about programs, not
because it violates the principles of "structured programming" which I
don't give a flying f$@& about.


> Not to mention that I extremely dislike this suggestion - it chops up into
> several parts the code what once has been a single function.

No, it chops into *two* parts code that was once a single function.
(Some programming languages allow you to define functions anywhere a
value is allowed, thus avoiding the need to chop the code up at all.)


> Btw, your code
> seems to have a blatant error: the function should have been declared as
>
> inline void f(A &a, B &b)

It depends entirely on whether or not A and B are bigger than the
natural word size of the machine you are compiling for. It makes no
sense to pass the machine's native integer type by reference for
example. Yeah, we hope a compiler will optimize these things away. But
who says A and B aren't typedefed to references anyway? Also, if you do
decide to pass something by reference, you may want to pass them as a
reference to a constant value, i.e. "A const & a".

C++ sure is a squishy language.

-thant

Andrei Alexandrescu (See Website For Email)

unread,
Mar 29, 2007, 5:29:13 AM3/29/07
to
Walter Bright wrote:
> Fortunately, scope(success) and scope(failure) are easily and robustly
> implementable using try-catch-finally:
>
> scope(failure) s;
>
> => try { ... } catch (o) { s; throw o; }

"Avoid using the symbols o, O, l, and I". 0stensible a11arming messages
shouId be issued by compi1ers :0).

Y0urs,

Andrei

Andrei Alexandrescu (See Website For Email)

unread,
Mar 29, 2007, 5:29:57 AM3/29/07
to
Zeljko Vrba wrote:
> On 2007-03-28, Thant Tessman <a...@standarddeviance.com> wrote:
>> inline void f(A a, B b) {
>> while (a) {
>> while (b) {
>> if (something) return;
>> }
>> // more code
>> }
>> }
>>
> The banning of goto was to promote "structured programming". In that line,
> structured programming has had another principle that people have, it seems,
> mostly forgotten: every function should have one entry and one exit.

A new SESE thread? We should start the practice of pasting our old
debates again; it saves time :o).

Andrei

Richard Corden

unread,
Mar 29, 2007, 5:31:46 AM3/29/07
to

Daniel T. wrote:
> "Michael K. O'Neill" <MikeAT...@nospam.hotmail.com> wrote:

[...]

>> It's difficult to see any principled, moral distinction between an "evil"
>> goto and supposedly "acceptable" constructs like break or continue, or
> even
>> an early return.
>
> So many people over the years have heard that "goto is harmful" and
> then, without asking why, have looked for reasons. They end up with a
> bunch of excuses like "goto can bypass constructors" which have nothing
> to do with Dijkstra's argument.

And this is not really an argument since 'goto' cannot bypass a
constructor as that would be a jump over an initialization. Similarly,
'goto' cannot be used to jump into a try block. [Of course compilers
may differ in QOI].


[...]

> ... Rubin presents two examples often cited whenever the

> subject comes up and says that because the program fragments he presents
> as solutions have fewer lines of code, fewer operators, and fewer tokens
> if goto is used, they are better.

I believe he uses these aspects, since they are the aspects used in
general to calculate complexity metrics. His point is that a program
with goto can actually less complex than a program without (if these
metrics are used).


"More importantly, the programmers who
> used gotos took less time to arrive at their solutions." says he. That
> last bit is especially egregious because safer solutions tend to take
> more time to create than dangerous solutions, so it is more an
> inditement of goto than a support of it. The letter makes no attempt to
> show any flaw in Dijkstra's argument.


IMHO the flaw with any blanket ban like this - is that it covers too
much. There are always exceptions to the rule. This may be an urban
myth, but a 'smart???' programmer working under a strict SESE and no
'goto' policy came up with the following code:

do
{
if (cond_1 )
{
break;
}

if (cond_2 )
{
break;
}

if (cond_3 )
{
break;
}


// ...

}
while (false);


Is this code really clearer than an alternative using 'goto' or multiple
returns?


Regards,

Richard

--
Richard Corden

Walter Bright

unread,
Mar 29, 2007, 6:19:53 PM3/29/07
to
Andrei Alexandrescu (See Website For Email) wrote:
> Walter Bright wrote:
>> Fortunately, scope(success) and scope(failure) are easily and robustly
>> implementable using try-catch-finally:
>>
>> scope(failure) s;
>>
>> => try { ... } catch (o) { s; throw o; }
>
> "Avoid using the symbols o, O, l, and I". 0stensible a11arming messages
> shouId be issued by compi1ers :0).
>
> Y0urs,
>
> Andrei
>

7ru3, but 'o' in this c4s3 is 4 compi1er gener4ted symb01 th3 us3r n3v3r
s33s.

Thant Tessman

unread,
Mar 29, 2007, 6:11:00 PM3/29/07
to
Thant Tessman wrote:
> Zeljko Vrba wrote:


[...]

>> Btw, your code


>> seems to have a blatant error: the function should have been declared as
>>
>> inline void f(A &a, B &b)
>
> It depends entirely on whether or not A and B are bigger than the

> natural word size of the machine you are compiling for. [...]

Never mind. I figured out that you're assuming that a and b might be
used in code beyond the nested loops. As a rule of thumb I try to avoid
using loop variables beyond the loops so I didn't consider it.

Thant Tessman

unread,
Mar 29, 2007, 6:13:55 PM3/29/07
to
Andrei Alexandrescu (See Website For Email) wrote:
> Thant Tessman wrote:

>> [...an example that avoided the use of goto...]


>
> This reeks much of the same smell as the (now, I hope, hackneyed)
> recommendation to make loops into classes just to use for_each with them.

I didn't use anything more exotic than a rather pedestrian function call
to avoid the use of goto in this situation.

[...]


-thant

Pete Becker

unread,
Mar 29, 2007, 6:11:04 PM3/29/07
to
Walter Bright wrote:
>
> Yet I see the problem as I failed to grasp the goto-less logic. I
> understood the goto one perfectly.
>

Exactly. Whenever someone says "this code is more readable than that,"
read it as "this code is easier for me to read than that." Readability
depends on what you're used to.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

Thant Tessman

unread,
Mar 29, 2007, 6:17:39 PM3/29/07
to
Tony Delroy wrote:

> [...] I find the kind of code where


> gotos sometimes seem the optimal fit include low-level parsing/lexing
> routines, language grammar analysis, state machines, and expression

> parsing. [...]

All of which is code that should be machine generated from separate
specifications more amenable to human reasoning.

-thant

Martin Bonner

unread,
Mar 29, 2007, 6:21:04 PM3/29/07
to
On Mar 29, 10:31 am, Richard Corden <richard_cor...@hotmail.com>
wrote:
> Daniel T. wrote:

But that *isn't* strict SESE. The do-while block has four exits
(three breaks and a fall through). Strict SESE doesn't allow break.
You have to write it as:

if (cond_1 )
{
// Do nothing
}
else if (cond_2 )
{
// Do nothing
}
else if (cond_3 )
{
// Do nothing
}
else
{
// ...
}

Or even:

if (cond_1 ||
cond_2 ||
cond_3 )
{
// Do nothing
}
else
{
// ...
}

Note: I would resist the temptation to add a ! to the above test, and
move the else code into the then block. It makes the expression to
complex. In fact, if cond_n are complex, it would almost certainly be
best to stick with my original formulation.

I suspect that your original example should have looked more like:

do
{
if (cond_1 )
{
break;
}

doStuff1();

if (cond_2 )
{
break;
}

doStuff2();

if (cond_3 )
{
break;
}

finishOff();

} while (false);

Strict SESE calls for:

if (! cond_1 )
{
doStuff1();
if (! cond_2 )
{
doStuff2();
if (! cond_3 )
{
finishOff();
}
}
}

which is not too bad, but once you get a few more conditions, it does
get messy.

Personally, I am not an advocate of SESE (although I don't like
multiple entry). I think breaks, early returns, and even gotos can
clarify code. I just don't think your example was very persuasive


--

Anand Hariharan

unread,
Mar 29, 2007, 6:38:31 PM3/29/07
to
On Mar 29, 12:24 am, "Sushrut Sardeshmukh" <bestbr...@gmail.com>

I know Francis will disagree, and I'll gladly defer to his wisdom, but
here are my comments to your code and your question:

Your code has exactly one pointer. What if there are multiple
resources? At each instance in your function when you make a check
for the return code or some invariant, and decide you cannot continue,
you are responsible to release all acquired resources *until that
point*.

Worse, at a later date, if you have to introduce another resource, you
will have to visit each exit point after this resource is acquired,
and make sure you release it at each of those exit points.

The code I showed above, in essence, is the same as Java's finally.
IOW, goto is not being used to circumvent contortions that might arise
due to religiously adhering to structured programming; rather a
pragmatic way to deal with errors and "exceptions" -- in the absence
of exceptions and RAII, of course.

- Anand

Daniel T.

unread,
Mar 29, 2007, 6:36:20 PM3/29/07
to
Richard Corden <richard...@hotmail.com> wrote:
> Daniel T. wrote:
> > "Michael K. O'Neill" <MikeAT...@nospam.hotmail.com> wrote:
>
> > ... Rubin presents two examples often cited whenever the subject
> > comes up and says that because the program fragments he presents
> > as solutions have fewer lines of code, fewer operators, and fewer
> > tokens if goto is used, they are better.
>
> I believe he uses these aspects, since they are the aspects used in
> general to calculate complexity metrics. His point is that a
> program with goto can actually less complex than a program without
> (if these metrics are used).

And Dijkstra says that using a different metric, the goto-less fragments
can be less complex. Dijkstra spent some time defending the importance
of the particular metric he was using, Rubin made no effort to do so.

> > "More importantly, the programmers who used gotos took less time
> > to arrive at their solutions." says he. That last bit is
> > especially egregious because safer solutions tend to take more
> > time to create than dangerous solutions, so it is more an
> > inditement of goto than a support of it. The letter makes no
> > attempt to show any flaw in Dijkstra's argument.
>
> IMHO the flaw with any blanket ban like this - is that it covers too
> much.

That is why it is so important to understand *why* Dijkstra came to the
conclusion he did. His argument doesn't "cover too much" it covers
exactly what it needs to cover. He readilly admits in the paper that
goto *can* be used without destroying the progress of the process.

> There are always exceptions to the rule.

Meaningless platitude. There are exceptions to the blanket statement
"don't use goto", but there are no exceptions (AFAIK there may be some
true mental giants in the world) to the statement "...our intellectual
powers are rather geared to master static relations and that our powers
to visualize processes evolving in time are relatively poorly developed"
(Dijkstra)

> This may be an urban
> myth, but a 'smart???' programmer working under a strict SESE and no
> 'goto' policy came up with the following code:
>
> do
> {
> if (cond_1 )
> {
> break;
> }
>
> if (cond_2 )
> {
> break;
> }
>
> if (cond_3 )
> {
> break;
> }
>
>
> // ...
>
> }
> while (false);

// next line


>
>
> Is this code really clearer than an alternative using 'goto' or multiple
> returns?

At least with the above, I can figure out what happened before "next
line" was hit without having to actually track the progress of the
program.

Here is an example fragment for you:

void bar() {
// some large chunk of code with "goto foo" at
// several different places
foo:
// What line was executed before we got here?
}

The question says it all. With block structured code, we know the answer
to the question.

--

Daniel T.

unread,
Mar 29, 2007, 6:36:18 PM3/29/07
to
Walter Bright <wal...@digitalmars-nospamm.com> wrote:

> Daniel T. wrote:
>
> > For example, put your finger at the point where the comment "rest
> > of the program" is and ask yourself what code was executed before
> > that point. In the latter example, one need only know what the
> > value of tmp, b, and a are (or would be if it still existed in the
> > case of tmp,) in order to know exactly what has transpired. In the
> > former case you cannot reconstitute the execution path. Maybe
> > foo() returned true, maybe the loop naturally fell out, or maybe
> > the entire while loop was skipped due to some other goto above it
> > that went to the out_a label. In using the goto, you have lost the
> > "progress of the process" as Dijkstra points out in his paper.
>
> Yet I see the problem as I failed to grasp the goto-less logic. I
> understood the goto one perfectly.

Let me try again to explain Dijkstra's paper (As I understand it at
least. :-)

[bringing back the examples]


> while(a) {
> while(b) {
> if(foo())
> goto out_a; // exit the outer loop
> }
> // more code
> }
> out_a:
> // rest of the program
>
> becomes:
>

> bool tmp = false;
> while(true){


> while(b && !(tmp = (foo() != 0))){
> // code which might change the
> // truth value of something
> }
> if(tmp or not a) break;
> // more code
> }
> // rest of the program

OK, let's pretend we run the code fragments in a debugger with a
break-point at the line immediately after the comment "rest of the
program". What was the last line executed? You have a list of variable
values and the stack pointer...

With the goto version, you *cannot* know unless you were methodically
stepping through the fragment. With the goto-less version, you can
simply look at the values of the variables and know.

... our intellectual powers are rather geared to master static

relations and that our powers to visualize processes evolving in time

are relatively poorly developed. For that reason we should do (as
wise programmers aware of our limitations) our utmost to shorten the
conceptual gap between the static program and the dynamic process, to
make the correspondence between the program (spread out in text
space) and the process (spread out in time) as trivial as possible.

Goto can make that correspondence between program and process more
complex.

I see a caveat to his paper however. Dijkstra was referring to a goto
command that could jump anywhere in the program whereas in C/C++ the
goto is localized to only its own function. This mitigates the problem
quite a bit and it *is* possible to write goto code in C that does not
increase the number of textual indexes needed to understand the process.
Your example however is not such.

Francis Glassborow

unread,
Mar 29, 2007, 6:37:45 PM3/29/07
to
In article <1175107636.6...@y80g2000hsf.googlegroups.com>,
Vladimir Marko <swe...@post.sk> writes

>I'm no fan of SESE. It's always been PITA when I used it.
>IMO, with goto you pretend to use the SESE while actually
>having multiple returns.

Yes, using goto to provide a single point of exit is to entirely miss
the motivation (however misguided :-) ) for SESE. SESE does not mean
there is a single return statement, it means that there is a single
logical point of return. Introducing state variables to ensure just one
return per function is another example of missing the spirit of SESE

SESE requires a single return statement but that is not sufficient.
--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Zeljko Vrba

unread,
Mar 29, 2007, 6:36:20 PM3/29/07
to
On 2007-03-29, Thant Tessman <a...@standarddeviance.com> wrote:
>> On 2007-03-28, Thant Tessman <a...@standarddeviance.com> wrote:
>
>> Btw, your code
>> seems to have a blatant error: the function should have been declared as
>>
>> inline void f(A &a, B &b)
>
> It depends entirely on whether or not A and B are bigger than the
> natural word size of the machine you are compiling for. It makes no
>
You have completely missed the point. The loop may modify a and b. Your
version (without references) will not make changes made to a and b in f
visible to its caller. Thus, you have broken the semantics of the original
code.

Francis Glassborow

unread,
Mar 29, 2007, 6:37:45 PM3/29/07
to
In article <1175120582.4...@d57g2000hsg.googlegroups.com>, Tony
Delroy <tony_i...@yahoo.co.uk> writes

>Please look at boost and Duff's Device, and if they're not enough, get
>back to me.
I am well familiar with Duff's Device and it was (note past tense) very
useful these days I have doubts that it has much practical use other
than on systems that are very, very resource constrained.

As for the use of goto in Boost libraries, I have reservations about the
implementation quality of some of those. They are well specified and
generally have good interfaces but that does not mean that
implementation is an example of best practice and with low maintenance
overheads + high readability (considering the proportion of generic
programming involved, readability would be hard anyway.)

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Francis Glassborow

unread,
Mar 30, 2007, 12:45:10 AM3/30/07
to
In article <1175182927.1...@r56g2000hsd.googlegroups.com>,
Anand Hariharan <mailto.anan...@gmail.com> writes

>The code I showed above, in essence, is the same as Java's finally.
>IOW, goto is not being used to circumvent contortions that might arise
>due to religiously adhering to structured programming; rather a
>pragmatic way to deal with errors and "exceptions" -- in the absence
>of exceptions and RAII, of course.

And that is one of the important points, C++ *has* better mechanisms.
goto is essential at assembler level but as we move to higher level
languages more and more of the places where goto was can be replaced by
more robust alternatives.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions:
http://www.spellen.org/youcandoit/projects

Keith H Duggar

unread,
Mar 30, 2007, 12:45:17 AM3/30/07
to
Alf P. Steinbach wrote:
> The only difference in the even and odd cases is that 'e' is 1 larger in
> the odd case. And this essentially boolean value is represented by the
> execution position.

Exactly. And that (eliminating a variable and some operations by using
code
position) is in fact one of Kuzmin's optimizations.

> Represent it as a variable instead.
>
> for( ;; )
> {
> f( x,y );
> if( y >= x ) { return ; }
> e += y + oddStep;
> ++y;
> oddStep = !oddStep;
> if( e >= 0 ) { --x; e -= x; }
> }

This adds an additional variable (oddStep) and increases the
operation count by two: !oddStep and y + oddStep.

Keith


--

Andrei Alexandrescu (See Website For Email)

unread,
Mar 30, 2007, 12:40:48 AM3/30/07
to
Walter Bright wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Walter Bright wrote:
>>> Fortunately, scope(success) and scope(failure) are easily and robustly
>>> implementable using try-catch-finally:
>>>
>>> scope(failure) s;
>>>
>>> => try { ... } catch (o) { s; throw o; }
>>
>> "Avoid using the symbols o, O, l, and I". 0stensible a11arming messages
>> shouId be issued by compi1ers :0).
>>
>> Y0urs,
>>
>> Andrei
>>
>
> 7ru3, but 'o' in this c4s3 is 4 compi1er gener4ted symb01 th3 us3r n3v3r
> s33s.

7h3n m4k3 it __o.

Andrei


{ Moderator's translation: "then make it __oo", the form "__o", with two
underscores, being reserved to the implementation. Anyway, this
subthread is closed for further leet-speak, unless it's really good (not
the obvious "_O"). Follow-ups in plain English, please. -mod/aps }

Andrei Alexandrescu (See Website For Email)

unread,
Mar 30, 2007, 12:49:46 AM3/30/07
to
Thant Tessman wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Thant Tessman wrote:
>
>>> [...an example that avoided the use of goto...]
>>
>> This reeks much of the same smell as the (now, I hope, hackneyed)
>> recommendation to make loops into classes just to use for_each with them.
>
> I didn't use anything more exotic than a rather pedestrian function call
> to avoid the use of goto in this situation.

Restating what the code does does not help the argument in the least.
:o) You force the programmer to go at top level and define a function
_and_ pass it the appropriate context, just to not use goto. That's
gratuitous and leads in most cases to less maintainable code than the
one it was supposed to improve on.


Andrei

Thant Tessman

unread,
Mar 30, 2007, 5:32:38 AM3/30/07
to
Andrei Alexandrescu (See Website For Email) wrote:
> Thant Tessman wrote:
>> Andrei Alexandrescu (See Website For Email) wrote:
>>> Thant Tessman wrote:
>>
>>>> [...an example that avoided the use of goto...]
>>>
>>> This reeks much of the same smell as the (now, I hope, hackneyed)
>>> recommendation to make loops into classes just to use for_each with
>>> them.
>>
>> I didn't use anything more exotic than a rather pedestrian function
>> call to avoid the use of goto in this situation.
>
> Restating what the code does does not help the argument in the least.
> :o)

Your response to my code transformation, referring to (I'm guessing)
controversial control flow constructs (that I know nothing about and
therefore have no opinion on), was apparently intended to suggest that
what I had done was somehow unnecessarily contorted.

My first (censored) response was to suggest (in less polite language)
that you might be over-analyzing the situation just a bit since I wasn't
doing anything particularly arcane or unorthodox (beyond my cavalier
rejection of SESE, which I will fully, nay, proudly admit to).

My second response is quoted above.


> You force the programmer to go at top level and define a function
> _and_ pass it the appropriate context, just to not use goto. That's
> gratuitous and leads in most cases to less maintainable code than the
> one it was supposed to improve on.

Gee, maybe it's possible to avoid function calls altogether. Maybe it's
possible to replace them entirely with gotos. I bet that this is
actually what compilers do now anyway. Maybe we can use compilers to
make code easier to understand by getting rid of all those obscuring
function calls.

-thant

peter koch larsen

unread,
Mar 30, 2007, 7:29:21 AM3/30/07
to
On 30 Mar., 06:49, "Andrei Alexandrescu (See Website For Email)"

<SeeWebsiteForEm...@erdani.org> wrote:
> Thant Tessman wrote:
> > Andrei Alexandrescu (See Website For Email) wrote:
> >> Thant Tessman wrote:
>
> >>> [...an example that avoided the use of goto...]
>
> >> This reeks much of the same smell as the (now, I hope, hackneyed)
> >> recommendation to make loops into classes just to use for_each with them.
>
> > I didn't use anything more exotic than a rather pedestrian function call
> > to avoid the use of goto in this situation.
>
> Restating what the code does does not help the argument in the least.
> :o) You force the programmer to go at top level and define a function
> _and_ pass it the appropriate context, just to not use goto. That's
> gratuitous and leads in most cases to less maintainable code than the
> one it was supposed to improve on.
>
But removing loops and inserting them into their own function is often
a good thing in its own right. It makes the function smaller and
easier to understand. I've just worked with a codebase where this was
not done. Functions were often very large (200 lines were common, and
1000 lines not uncommon), and often consisted of loops within loops
and/or loops following loops. Moving loops out of the code would
decreased the complexity a lot and make the code far more
maintainable.

/Peter

Richard Corden

unread,
Mar 30, 2007, 7:28:20 AM3/30/07
to
Daniel T. wrote:
> Richard Corden <richard...@hotmail.com> wrote:
>> Daniel T. wrote:
>>> ... Rubin presents two examples often cited whenever the subject
>>> comes up and says that because the program fragments he presents
>>> as solutions have fewer lines of code, fewer operators, and fewer
>>> tokens if goto is used, they are better.

[...]

> And Dijkstra says that using a different metric, the goto-less fragments
> can be less complex. Dijkstra spent some time defending the importance
> of the particular metric he was using, Rubin made no effort to do so.

I believe Rubin is referring to a commonly used complexity metric, ie.
the "Halstead Complexity Metric". It is calculated using operators,
punctuators and number of lines etc. I don't think it is up to Rubin to
defend it.

[...]

>> IMHO the flaw with any blanket ban like this - is that it covers too
>> much.
>
> That is why it is so important to understand *why* Dijkstra came to the
> conclusion he did. His argument doesn't "cover too much" it covers
> exactly what it needs to cover. He readilly admits in the paper that
> goto *can* be used without destroying the progress of the process.
>

I must admit - I found it hard to find where he 'readily' admits that
goto can be used. But if he does admit this - then actually I'm on his
side. Personally, I cannot remember ever needing to use 'goto' in my
code - but should an example arise which would be clearer by using
'goto' then I think 'goto' should be used in favour of a solution that
would result in less clear code.


>> There are always exceptions to the rule.
>
> Meaningless platitude.

Our business is coding standard enforcement. I believe I can say with a
degree of certainty that in relation to a coding standard there are
"always exceptions to the rule". (It costs us time and money to support
'exceptions' to coding standard rules on a daily basis).

[...]

>
> Here is an example fragment for you:
>
> void bar() {
> // some large chunk of code with "goto foo" at
> // several different places
> foo:
> // What line was executed before we got here?
> }
>
> The question says it all. With block structured code, we know the answer
> to the question.
>

The answer is it depends on how large the chunk of code is. It also
depends on why you needed 'goto'. Using 'goto' for its own sake is not
a good reason either - if the code can be expressed using other
constructs that more correctly define the behaviour then use them.

My "current" opinion is: "A goto that jumps forward to a statement label
in an outer enclosing scope probably requires about as much thought and
consideration as any other jump construct."

I would still ban, backward jumps and a jump into nested scopes!


Kind Regards,

Richard


--
Richard Corden

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Ulrich Eckhardt

unread,
Mar 30, 2007, 7:30:38 AM3/30/07
to
Zeljko Vrba wrote:
> The banning of goto was to promote "structured programming". In that
> line, structured programming has had another principle that people have,
> it seems, mostly forgotten: every function should have one entry and
> one exit.

Well, it might be that structured programming does have the rule about only
having one exit, but in the C++ flavour of structured programming it is not
generally accepted. After all, a function might throw, so you always have
to consider at least two possible ways to leave a function.

Sorry, but your statement simply is outdated or not applicable to C++, but
at least it doesn't resemble accepted practice.

Uli

--
Sator Laser GmbH
Geschäftsführer: Ronald Boers Steuernummer: 02/858/00757
Amtsgericht Hamburg HR B62 932 USt-Id.Nr.: DE183047360

Daniel T.

unread,
Mar 30, 2007, 9:36:55 AM3/30/07
to
In article <573us6F...@mid.individual.net>,
Richard Corden <richard...@hotmail.com> wrote:

> > Here is an example fragment for you:
> >
> > void bar() {
> > // some large chunk of code with "goto foo" at
> > // several different places
> > foo:
> > // What line was executed before we got here?
> > }
> >
> > The question says it all. With block structured code, we know the answer
> > to the question.
> >
>
> The answer is it depends on how large the chunk of code is. It also
> depends on why you needed 'goto'. Using 'goto' for its own sake is not
> a good reason either - if the code can be expressed using other
> constructs that more correctly define the behaviour then use them.

Exactly, it depends on many things. When looking at the text of a
program, as soon as you see a label you have lost the progress of the
process, you have to scan the entire function for gotos to see where the
program counter might have come from. And back in Dijkstra's day, for
many languages goto commands could cut across procedures which would
mean scanning the entire program. In a function that has no labels, you
know at every point in the function exactly what the previous line was
(possibly by examining some variable values.)

Funny, people keep comparing goto with break and early returns but there
is no comparison. Procedures are actually closer to acting like gotos
(in BASIC we used gosub.)

As soon as we include in our language procedures we must admit that a
single textual index is no longer sufficient. In the case that a
textual index points to the interior of a procedure body the dynamic
progress is only characterized when we also give to which call of the
procedure we refer. With the inclusion of procedures we can
characterize the progress of the process via a sequence of textual
indices, the length of this sequence being equal to the dynamic depth
of procedure calling.

So without goto or procedures, a single "textual index" is all you need.
By admitting procedures you need a stack of textual indexes. With goto,
you need one for each label in the program. The dynamic behavior of the
program becomes harder to parse.

Again, the C/C++ languages mitigate this problem by refusing to allow
goto to jump outside the scope of the function that contains it. I think
Dijkstra would have applauded such a limitation and maybe would have
even taken back some of what he said about the command.

> My "current" opinion is: "A goto that jumps forward to a statement label
> in an outer enclosing scope probably requires about as much thought and
> consideration as any other jump construct."
>
> I would still ban, backward jumps and a jump into nested scopes!

An exception to every rule... You said it yourself. Of course, there are
exceptions to that rule as well...

--

Daniel T.

unread,
Mar 30, 2007, 9:38:46 AM3/30/07
to
"Keith H Duggar" <dug...@alum.mit.edu> wrote:
> Alf P. Steinbach wrote:
>
> > The only difference in the even and odd cases is that 'e' is 1
> > larger in the odd case. And this essentially boolean value is
> > represented by the execution position.
>
> Exactly. And that (eliminating a variable and some operations by
> using code position) is in fact one of Kuzmin's optimizations.

There you go.

...our intellectual powers are rather geared to master static


relations and that our powers to visualize processes evolving in time
are relatively poorly developed. For that reason we should do (as
wise programmers aware of our limitations) our utmost to shorten the
conceptual gap between the static program and the dynamic process, to
make the correspondence between the program (spread out in text
space) and the process (spread out in time) as trivial as possible.

(Dijkstra)

Message has been deleted
It is loading more messages.
0 new messages