May 01, 2006
I can also show you awful OOP.  By your logic, OOP is thereby flawed and should never be used.

Yet, that is not a good assertion.  Just because a goto can be used to do evil does not mean it is, necessarily, evil - as long as it is used only for good.  Just like anything else.

But obviously, this is not good and evil.  Still.

-[Unknown]


> I *do* understand them, and I also do know, that they are useful and whatnot. Still, I don't like them - they are a relict of early C times. But now we've got neat, mighty conditional loops - what do we need GOTOs for?
> 
> A friend of mine once wrote such code:
> 
> <code>
> label:
> doSomething( );
> 
> if ( condition )
>     goto label;
> </code>
> 
> That *is* a do-while loop.
> 
> <code>
> do {
>     doSomething( );
> } while ( condition )
> </code>
> 
> Effectively, those two construct are the same, but the second one is, IMO, far better readable (readable as in recognization of what a program is doing).
> 
> Regards,
> Alexander Panek
May 01, 2006
On Mon, 01 May 2006 00:21:29 +0200, Alexander Panek wrote:


...

> A friend of mine once wrote such code:
> 
> <code>
> label:
> doSomething( );
> 
> if ( condition )
> 	goto label;
> </code>
> 
> That *is* a do-while loop.
> 
> <code>
> do {
> 	doSomething( );
> } while ( condition )
> </code>

The problem, IMHO, with this is not the 'goto' per se, but the label.

The existence of a label opens the possibility that somewhere *else* in the code is a reference to that label and so as a code maintainer, I must examine all the code for such a reference. This takes time (even though it might only be a seconds using a good editor) it does add further maintenance cost. And if I do find other references, I need to examine the implications of any change I make to the local area around the label to ensure there are no unintended side-effects due to code jumping to the label ... more time used up!

It is for that reason that controlled gotos such as 'do-while' are preferred to uncontrolled gotos. The 'goto' statement is not the real problem, its the label that's the issue.

In fact, I'm a firm believer that if a section of code contains a 'goto'/'label' in order to improve the efficiency or legibility then it is a sign that there is a higher level construct missing in the language. Knuth has given us a few examples where 'goto' does improve the reader's knowledge of the intent of the author or removes redundantly executed code. I regard this as a failing in the language used to encode the algorithms, because the use of labels that can be reached from outside the context of the immediate section is a maintenance cost we don't need.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocracy!"
1/05/2006 12:46:16 PM
May 01, 2006
Derek Parnell wrote:
> The use of 'goto' has an inherinent cost in terms of ongoing maintenance of code. In short, it adds to the time it takes to analyse code prior to making changes that do not have unintended side-effects. That cost must be justifed. Therefore one should only use 'goto' in situation in which the cost of its use can be offset by some other gain in the code. Such a gain is performance in a performace-critical section of code. I'm not sure if there are any other situations it is cost-justified.

A goto is also useful:

1) to avoid excessive diffs caused by refactoring code

2) when one wants to build a control structure that just doesn't fit into the usual if-else, while, for, etc.

3) to avoid the creation of silly 'flag' state variables

4) to create an efficient state machine

5) as output from program generators

6) to, for instance, collect all error handling code in one spot in a function
May 01, 2006
Walter Bright wrote:
> Derek Parnell wrote:
> 
>> The use of 'goto' has an inherinent cost in terms of ongoing maintenance of code. In short, it adds to the time it takes to analyse code prior to making changes that do not have unintended side-effects. That cost must be justifed. Therefore one should only use 'goto' in situation in which the cost of its use can be offset by some other gain in the code. Such a gain is performance in a performace-critical section of code. I'm not sure if there are any other situations it is cost-justified.
> 
> 
> A goto is also useful:
> 
> 1) to avoid excessive diffs caused by refactoring code
> 
> 2) when one wants to build a control structure that just doesn't fit into the usual if-else, while, for, etc.
> 
> 3) to avoid the creation of silly 'flag' state variables
> 
> 4) to create an efficient state machine
> 
> 5) as output from program generators
> 
> 6) to, for instance, collect all error handling code in one spot in a function


#4 is definately useful within a switch(){}

Alternate design strategies aside, I was always told that goto, in general, lead to *less* efficient code. Didn't compilers (perhaps in the past) disable the optimizer for functions with one or more instances of goto? Doesn't it mess with flow analysis, or something?
May 01, 2006
In article <e30i88$1q4n$1@digitaldaemon.com>, Walter Bright says...
>
>I know goto's are evil, but I tend to write such as:
>
>int i;
>for (i=0; i<10; i++)
>{
>   Lretry:
>     if (string.substr(i,1) == something)
>     {
>         i += some_other_function();
>         goto Lretry;
>     }
>     else if (string.substr(i,1) == something_else)
>     {
>         i += some_other_function2();
>         goto Lretry;
>     }
>     // Otherwise, simply execute the "i++" and re-test
>}

The problem here is the test condition is not being executed.  In theory, "i +=
some_other_function()"
could increment i beyond the value desired in the for loop conditional-clause.
The Lretry would not
officially retry the test condition and could, therefore, potentially execute on
values of i that are
undesired by being outside the scope of the for loop, introducing a trait that a
well-written program
should not include.

- Rick C. Hodgin


May 01, 2006
In article <op.s8tl32d56b8z09@ginger.vic.bigpond.net.au>, Derek Parnell says...
>
>> Anyways, easy to add keyword, but in the same place as "continue", so why do it?
>
>Because 'continue' and 'retry' are not the same thing. 'continue' means go to the next iteration, and 'retry' means repeat the same iteration.
>
>....CONCEPTUAL CODE....
>
>    for_start:
>        init_code;
>    for_test:
>        if ( end_condition ) goto for_end;
>    for_body:
>        do_something;
>        if <A> goto for_index; // continue
>        if <B> goto for_test; // retry
>        if <C> goto for_start; // restart
>        if <D> goto for_end; // break;
>    for_index:
>        update_index;
>        goto for_test;
>    for_end:

Derek, you nailed it here.  These should be the exact keywords used for this
concept, because these are
the sum total of mechanisms which could be applied.  And they have the added
benefit of
accomplishing the same things that can be accomplished in other ways, but in a
more straight-forward
and elegent manner.  I applaud your contribution.

One other potentially desirable condition that I could've used a few times is this:

>....CONCEPTUAL CODE....
>
>    for_start:
>        init_code;
>    for_test:
>        if ( end_condition ) goto for_end;
>    for_body:
>        do_something;
>        if <A> goto for_index; // continue
>        if <B> goto for_test; // retry
>        if <C> goto for_start; // restart
>        if <D> goto for_end; // break;
>        if <E> goto for_invalidate_end; // ibreak
>    for_index:
>        update_index;
>        goto for_test;
>    for_invalidate_end:
>        set test value to some value indicating hard break
>    for_end:

I propose the actual syntax for this invalidate-break to be:
for (i=0; i<10; i++)
{
// Code goes here for loop
} (i = -1);

With the invalidated value being specified at the end of the for loop as the "(i
= -1)" code.  This would
allow instances where the for loop was exited through a hard ibreak command to
set the value to some
identifiable condition in an elegant manner.  I further propose that the block
of code contained there
could also be either a series of semicolon delimited commands (which would
execute multiple
instructions) or a block of code enclosed by braces within the trailing
parenthesis, as in:

for (i=0; i<10; i++)
{
// Code goes here for loop
} ({
// Invalidation code would go here
});

These are some thoughts I've had to make the elegence of the programming
concepts more straight-
forward, to be supported by the compiler, and to remove the need for certain
types of work-arounds
right now for (perhaps even not so common) bits of code (but rather code that
needs to work in this
way, and to do so in a straight-forward manner).

- Rick C. Hodgin


May 01, 2006
On Sun, 30 Apr 2006 20:06:34 -0700, Walter Bright wrote:

> Derek Parnell wrote:
>> The use of 'goto' has an inherinent cost in terms of ongoing maintenance of code.

...

>> I'm not sure if there are any other situations it is cost-justified.

> A goto is also useful:

Thanks Walter. I don't want to take up any of your time so feel free to ignore this response.

I just want to repeat that my concern with the use of 'goto' and labels is that they add to the cost of maintaining source code. If that cost can be justified or offset by something else then fine. Otherwise just don't do it.

> 1) to avoid excessive diffs caused by refactoring code

If by 'refactoring' code you mean reorganizing it so that its structure is improved then I don't see how adding 'goto' is going to achieve that. But even if it did, is the ongoing cost of cosmetic 'goto' statements worth the once-off cost of a manually review of a large diff due to lots of code movement? If it is then fine, use goto, otherwise suck it up and get on with improving the source code for future maintainers.

> 2) when one wants to build a control structure that just doesn't fit into the usual if-else, while, for, etc.

This is a common excuse for goto usage. But again if the special structure is justified in terms of ongoing maintenance costs then everything is just fine. However I suspect that in most cases the 'special' is not worth it. But also, this could be used as an example of a missing construct in the language and that this is emulated using uncontrolled goto statements. Such is the case with a 'retry' concept and that's why I think it would be a useful addition to D.

> 3) to avoid the creation of silly 'flag' state variables

Yes. Knuth often points to this situation as a reason to use goto. The 'flag' variable is conceptually redundant and can be expensive to use at run-time. And I see this as another opportunity for a language to evolve so that such 'flags' are both avoided and the 'goto' used in their absence is also avoided. It would be *not* hard to generalize this situation so that a new syntax could be introduced to cater for it, as it is fairly common.

> 4) to create an efficient state machine

Even though state machines are reasonably rare, they are very handy in some situations. Again, it would not be hard for a language to come up with a decent syntax to help people encode a state machine without uncontrolled goto statements and to help the compiler generate efficient object code. If there is specific syntax for state machines, it will reduce maintenance costs and might even help people see where they can use them rather than some other construct.

> 5) as output from program generators

The output from these are not usually designed for human readers nor designed to be directly maintained. Therefore the use of goto statements has some place in this sort of output. In fact, it is metaphorically machine code.

> 6) to, for instance, collect all error handling code in one spot in a function

Yes, this is a very common usage for goto statements. Not so much as a performance enhancer because errors are supposed to be infrequent, but to improve source code maintainability. However, I believe that the benefit of goto usage here is lost due to the 'uncontrolled' nature of it. It introduces labels that can theoretically be reached from places other than the error handlers. In spite of that, I feel that this is a prime candidate for new syntax to deal with the problem of consolidating error handling code. It could be thought of an extension to D's 'try-catch' and 'scope' constructs, so I would encourage you to consider further evolving D into a language to delight code authors and maintainers, and also compiler writers.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocracy!"
1/05/2006 2:12:33 PM
May 01, 2006
kris wrote:
> Alternate design strategies aside, I was always told that goto, in general, lead to *less* efficient code. Didn't compilers (perhaps in the past) disable the optimizer for functions with one or more instances of goto? Doesn't it mess with flow analysis, or something?

I don't think any compiler built since 1982 had such limitations. In fact, the way the DM optimizer works is by converting all constructs to goto's and *then* operating on it. The algorithms to do this are well known, and are even in the Dragon Book (vintage 1979). Goto's will not adversely affect optimization at all.
May 01, 2006
Walter Bright wrote:
> kris wrote:
> 
>> Alternate design strategies aside, I was always told that goto, in general, lead to *less* efficient code. Didn't compilers (perhaps in the past) disable the optimizer for functions with one or more instances of goto? Doesn't it mess with flow analysis, or something?
> 
> 
> I don't think any compiler built since 1982 had such limitations. In fact, the way the DM optimizer works is by converting all constructs to goto's and *then* operating on it. The algorithms to do this are well known, and are even in the Dragon Book (vintage 1979). Goto's will not adversely affect optimization at all.

hehe ;)

Obviously been a while since I looked then ... I recall MWC being like that, and also the, umm, Lattice or Aztec -- a bit foggy now.

Oh well ... thanks.
May 01, 2006
Walter Bright wrote:

> A goto is also useful:
[...]
> 6) to, for instance, collect all error handling code in one spot in a function

Apple uses this technique extensively in their "Carbon" programs (C).

They just hide it away with some macros they devised back in 1992...
http://www.mactech.com/articles/develop/issue_11/Parent_final.html

They are still present in /usr/include/AssertMacros.h, and in Carbon.
See http://developer.apple.com/carbon, and http://tinyurl.com/pk94g

And yes, other higher level languages would use exceptions instead. ;)

--anders