From: Phil Carmody on
Patricia Shanahan <pats(a)acm.org> writes:
> Alexei A. Frounze wrote:
> ...
>> Surprisingly, my code is pretty clean with gotos, which, btw, I use
>> just for almost exclusively 2 things:
>> - breaking out of nested loops (not always, if I can do that w/o
>> writing more than two lines of code, I don't use goto)
>> - jumping to the common cleanup code at the end of the function when I
>> detect some error
> ...
>
> When I was first considering using Java for a project, I was a little
> worried about the lack of goto.
>
> I knew I had written a couple of gotos in C and maintained code
> containing goto that would have had to be much more convoluted without
> it. When I analyzed those uses of goto, I realized they were all in
> those two categories, mainly the common cleanup code case.
>
> That meant I would not need goto in a language with try-finally and
> named loop break.

I'm not a java person at all, but from what I understand try-finally
doesn't do what I use goto for, namely error-path cleanup. If, according
to Sun, "the finally block always executes when the try block exits",
then it's not error-path clean-up at all - it's unconditional cleanup.
Which is completely not what you want in a function whose job is to
acquire a bunch of resources.

Phil
--
I find the easiest thing to do is to k/f myself and just troll away
-- David Melville on r.a.s.f1
From: Patricia Shanahan on
Phil Carmody wrote:
> Patricia Shanahan <pats(a)acm.org> writes:
>> Alexei A. Frounze wrote:
>> ...
>>> Surprisingly, my code is pretty clean with gotos, which, btw, I use
>>> just for almost exclusively 2 things:
>>> - breaking out of nested loops (not always, if I can do that w/o
>>> writing more than two lines of code, I don't use goto)
>>> - jumping to the common cleanup code at the end of the function when I
>>> detect some error
>> ...
>>
>> When I was first considering using Java for a project, I was a little
>> worried about the lack of goto.
>>
>> I knew I had written a couple of gotos in C and maintained code
>> containing goto that would have had to be much more convoluted without
>> it. When I analyzed those uses of goto, I realized they were all in
>> those two categories, mainly the common cleanup code case.
>>
>> That meant I would not need goto in a language with try-finally and
>> named loop break.
>
> I'm not a java person at all, but from what I understand try-finally
> doesn't do what I use goto for, namely error-path cleanup. If, according
> to Sun, "the finally block always executes when the try block exits",
> then it's not error-path clean-up at all - it's unconditional cleanup.
> Which is completely not what you want in a function whose job is to
> acquire a bunch of resources.
....

I should have mentioned the use of a catch block to deal with
error-specific clean-up. The finally block is, indeed, the place for
unconditional clean-up.

Of course, memory clean-up is not an issue in Java, but there are other
resources that need explicit handling.

Patricia
From: Keith H Duggar on
On Apr 24, 6:41 pm, James Kanze <james.ka...(a)gmail.com> wrote:
> On Apr 24, 5:12 pm, "Daniel T." <danie...(a)earthlink.net> wrote:
>
> > "Leigh Johnston" <le...(a)i42.co.uk> wrote:
>
> [...]
>
> > In C and C++, goto is sufficiently restricted that as long as
> > your functions are small, it is largely harmless.
>
> In C and C++, if your functions are small enough, goto is
> largely harmless. And also useless. All of the examples I've
> seen defending goto introduce excessively complex functions in
> order to justify it.

The Kuzmin circle tracing algorithm is certainly not "excessively
complex" and is an (elegant) example of goto being /necessary/ to
to provide the optimal solution in some very real and important
scenarios. There was a moderated flame war about this nine months
ago culminating with these final posts

http://groups.google.com/group/comp.lang.c++.moderated/msg/3ac2368e485e740d
http://groups.google.com/group/comp.lang.c++.moderated/msg/5beca2fac77f7ab9

that empirically proved beyond any contestation at the time that
the goto version was optimal in some scenarios. All the source
code, scripts, etc are still available at

http://www.duggar.org/pub/code/circle/

to anyone who wishes to /rationally/ challenge the results with
empirical evidence. Otherwise continued unconditional anti-goto
preaching is simply anti-intellectual religion and certainly not
computer science.

Note these empirical results could (should?) have been "expected"
from the fact that Knuth already mathematically proved, decades
ago, that certain goto structures cannot be transformed into the
"structured" forms without introducing additional calculations or
code duplication both of which can be suboptimal on both old and
modern physical platforms not only on abstract computers.

Finally, if you do try and measure results note that the provided
code takes exceptional care when it comes to certain things that
to the naive might seem unimportant such as removal of constants,
randomization, control of inlining, avoidance of monolithic
compilation, etc. That is all /necessary/ for accurate profiling
which can be tricky to say the least. That was one source of the
disagreement in that original thread, ie one participant who
thought he was "all that" was simply ignorant of many of those
real world profiling and measurement considerations.

Subsequently I discussed that flame war with one of the worlds
genius compiler writers who confirmed the necessity of the inlining
etc controls explained above. However, he also added that in his
experience it is pointless to argue with the anti-goto mob because
it is a religion that ignores all inconvenient empirical evidence.

KHD
From: Nick on
"Alexei A. Frounze" <alexfrunews(a)gmail.com> writes:

> Surprisingly, my code is pretty clean with gotos, which, btw, I use
> just for almost exclusively 2 things:
> - breaking out of nested loops (not always, if I can do that w/o
> writing more than two lines of code, I don't use goto)
> - jumping to the common cleanup code at the end of the function when I
> detect some error
> I get by without goto in almost all other situations. I don't see
> what's not natural here. It's a clearly written and structured code,
> that is easy to follow, without surprises, without bloat. Of course,
> if you never need to do any cleanup or you never check error
> conditions or rely heavily on C++ exceptions, the 2nd use may be just
> unnatural to you as it is to me since I'm programming C, mixed C and C+
> + and I often have to deal explicitly with resource allocation.

I've just looked at my pile of code and there are no actual gotos in
there (there is a setjmp/longjmp pair, and a fair smattering of breaks,
continues and returns from part way through functions).

There seems to be a fairly common situation when you are programming,
particularly in C where you have to do a lot of stuff yourself, that
there isn't a "nice" way to deal with. This is when you have 3 or 4
lines of code that need to be executed under conditional circumstances
and in different but related places.

Making them into functions makes reading the code harder, and they don't
really make sense as a conceptual chunk of code. Embedding them in the
code can lead to convoluted flow control - and it's here that goto and
various other tricks tend to get invoked.

The clean-up example is a common one, but it's not the only one.

Just today I found myself in such a situation where I had two such
blocks which, depending on a couple of conditions, I wanted to execute
one, the other, or both in both orders - right in the middle of a large
function. So putting the code in functions several pages away from
where they were needed wasn't nice, and short of jumping around (either
with a loop even though there is only a single pass, or with goto) the
only other solution is to replicate the code.

In the end I compromised and with a bit of playing around was able to
reduce the shorter to a single line of fairly straightforward code, so
didn't mind repeating it inside conditionals either side of the larger
one. Still not a perfect solution of course.
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
From: Dave Harris on
leigh(a)i42.co.uk (Leigh Johnston) wrote (abridged):
> > Why not use break instead? Does the same thing, spares you from
> > having to define a label.
> >
>
> Because break only breaks out of the innermost loop, using goto to
> break out of nested loops is one of the few sensible uses of goto.

If you can't use return either, then it sounds like you have a function
which has a loop, then another nested loop, and then a bit more code
outside of both loops. At some point you have to wonder whether the
function is doing too many different things.

For example, instead of:

void process( char *filename ) {
if (FILE *fp = fopen( filename, "w" )) {
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
if (i == 5 && j == 5)
goto doubleBreak;
fprintf( fp, "%d %d", i, j );
}
}
doubleBreak:
fclose( fp );
}
}

use two functions:

void process( char *filename ) {
if (FILE *fp = fopen( filename, "w" )) {
process2( fp );
fclose( fp );
}
}

void process2( FILE *fp ) {
for (int i = 0; i < 10; ++i) {
for (int j = 0; j < 10; ++j) {
if (i == 5 && j == 5)
return;
fprintf( fp, "%d %d", i, j );
}
}
}

Here the first function handles opening and closing the file, and the
second one handles the actual output logic. This is a clean division of
responsibilities. The functions show a lot of cohesion. It's good to get
the fclose() in the same function as fopen() so we can be sure they pair
up correctly. The second function doesn't care about filenames, so it
could also be used with stdout or anything else the FILE abstraction can
write to. Because it doesn't need to clean up the file, it can use a
simple return statement.

In most cases, needing a goto is a sign a function is trying to do too
many things that lack cohesion. This can be true even if the function is
only 8 lines long. It's often a good idea to separate "acquiring a
resource" from "using a resource".

-- Dave Harris, Nottingham, UK.