From: James Van Buskirk on
"Alexei A. Frounze" <alexfrunews(a)gmail.com> wrote in message
news:aab23e01-b4d4-44c4-a136-a619da00a3f7(a)m24g2000prc.googlegroups.com...

> I wish there were distinct breaks for loops and switches as well as
> multi-level breaks for nested loops. goto's at times are the least
> evil since they don't require you to implement extra variables to
> break out of nested loops and they help to simplify function cleanup
> code (where resources are being freed on various conditions).

Amusing that Fortran has a mechanism to break out of nested loops
and permits one to use internal subroutines for function cleanup,
not to mention no fall-through in SELECT CASE constructs. These uses
of goto are simply artifacts of the limitations of C-style languages.

--
write(*,*) transfer((/17.392111325966148d0,6.5794487871554595D-85, &
6.0134700243160014d-154/),(/'x'/)); end


From: Alexei A. Frounze on
On Apr 25, 6:56 am, Patricia Shanahan <p...(a)acm.org> wrote:
> 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.
>
> Patricia

Of course, you could do that. And even if it was plain C but with
removed goto, you'd still be able to do your work.

Alex
From: Alexei A. Frounze on
On Apr 25, 8:52 am, Nick <3-nos...(a)temporary-address.org.uk> wrote:
> "Alexei A. Frounze" <alexfrun...(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

I don't know if this would work or not for your specific case, but if
blocks are sufficiently large and it's exactly one or both in either
order in the same place, then you could theoretically do something
like this:

#include <stdio.h>
int main(void)
{
const int ss[4][2] =
{
{ 1, 1 },
{ 2, 2 },
{ 1, 2 },
{ 2, 1 }
};
int i, cnt, start, stop, var;

for (i = 0; i < 4; i++)
{
start = ss[i][0];
stop = ss[i][1];

for (var = start, cnt = 1 + (start != stop);
cnt--;
var += (stop >= start) ? 1 : -1)
{
if (var == 1) printf("block 1 ");
else if (var == 2) printf("block 2 ");
}
printf("\n");
}

return 0;
}

Alex
From: Patricia Shanahan on
Alexei A. Frounze wrote:
> On Apr 25, 6:56 am, Patricia Shanahan <p...(a)acm.org> wrote:
>> 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.
>>
>> Patricia
>
> Of course, you could do that. And even if it was plain C but with
> removed goto, you'd still be able to do your work.

That depends on the definition of "do your work". C with goto removed
would remain Turing-complete. The issue is one of clarity and simplicity
of the code.

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

> On Apr 25, 8:52 am, Nick <3-nos...(a)temporary-address.org.uk> wrote:
>>
>> 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.
>
> I don't know if this would work or not for your specific case, but if
> blocks are sufficiently large and it's exactly one or both in either
> order in the same place, then you could theoretically do something
> like this:
>
> #include <stdio.h>
> int main(void)
> {
> const int ss[4][2] =
> {
> { 1, 1 },
> { 2, 2 },
> { 1, 2 },
> { 2, 1 }
> };
> int i, cnt, start, stop, var;
>
> for (i = 0; i < 4; i++)
> {
> start = ss[i][0];
> stop = ss[i][1];
>
> for (var = start, cnt = 1 + (start != stop);
> cnt--;
> var += (stop >= start) ? 1 : -1)
> {
> if (var == 1) printf("block 1 ");
> else if (var == 2) printf("block 2 ");
> }
> printf("\n");
> }
>
> return 0;
> }

That's the sort of thing (the var loop) that I meant by playing around
with loops. That is just so much more confusing than:

/* framework that sets do_first, do_second and first_is_first from array */
if(do_first && first_is_first)
printf("block 1\n");
if(do_second)
printf("block 2\n");
if(do_first && !first_is_first)
printf("block 1\n");

Which is exactly the problem - this one is clear, but gets messy if
"block 1" is a few lines but not obviously a function. Yours avoids
that, but is far from clear at first sight why it's looping.

If I was going for a loop, I'd be far more likely to set those three
variables, as for the above code and then create another flag and do:

do_first_this_time = do_first && first_is_first;
for(;;) {
if(do_first_at_all)
printf("Block 1\n");
if(do_second) {
printf("Block 2\n");
do_second = false;
}
if(do_first && !first_is_first) {
do_first_this_time = true;
continue;
} else
break;
}

Yes, pretty hideous. I still prefer it to yours though!
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk