in reply to Re: Re: block-based programming...
in thread block-based programming...

Gotos (and their P.C. cousins "abused exceptions") must die. They lead to poorly maintainable code that is both hard to read and trace.
There's no reason they lead to poorly maintainable code. They only lead to poorly maintainable code if they are misused. But it isn't too difficult to write spaghetti code using OO and no gotos - but that isn't a reason to say that OO must die. Perhaps you should read Knuth's paper "Structured programming with Go Tos", where he shows that if used appropriately, use of gotos is fine.

Quoting from my own work, part of a C program I modified last week:

__close1: if (close (soc) < 0) { if (errno == EINTR) { goto __close1; } perror ("close"); exit (1); }
I don't think this is less maintainable than writing a loop.

Abigail

Replies are listed 'Best First'.
Re: Re: block-based programming...
by flyingmoose (Priest) on Apr 22, 2004 at 16:09 UTC
    Gotos are almost as controversial as what constitutes good OO style. But they shouldn't be, since every construct that can be written with a goto can be written more clearly without one. I definitely agree both gotos and messy OO can obfuscate flow-control, so gotos are not the only evil. Here's how I would have done it:

    # keep trying to close socket until we succeed while (close(soc) < 0) { if (errno != EINTR) { # wasn't interrupted, this is some other failure, bail! perror("close"); exit 1; } }

    Your example is certaintly not less maintainble (yet), but this "block based" stuff above is an abomination when higher-level languages have more advanced constructs. That block based idea is fine for assembler or BASIC. Still, use of gotos encourages further use of gotos, and your particular use of goto and if's is logically a loop ... so just use the loop!

      ...every construct that can be written with a goto can be written more clearly without one.

      Try to rewrite TheDamian's Switch without the key goto $__; I dare you. Until you can do it, you haven't demonstrated that everything that can be written with a goto can be written without one (let alone written more clearly).

      More generally read the thread at (Ovid) Re: Re (tilly) 2: Paradigm Shift - Don't use strict to find out my opinion on when it is justified.

      The paper of Knuth's that was referred to there gives several other good reasons to use goto in at least some languages. Most of them boil down to the observation that there are many algorithms that can more efficiently be written with goto than without. At least in some languages.

      But not in Perl. A theorem that Knuth refers to from the literature is that any flow of control that can be achieved with goto can be achieved with nested loops and named loop control. Therefore in Perl you need extraordinary reasons to really need goto. (TheDamian had an example that I believe to be exactly that extraordinary.)

      Incidentally at Re: Re (tilly) 4: Paradigm Shift - when to use goto you will find a pre-processor macro from TheDamian showing you how to get named loops in C++. It uses goto, but considering that its purpose is to replace gotos that people write by hand with a more structured alternative, you may appreciate it.

      UPDATE: I just checked. It seems that TheDamian renamed $__ at some point. He now has labels named "C_A_S_E_$casecounter" instead.
      And you think that's more clear? For the sake of removing a goto, you introduce a while, which you, except for one specific case, aren't using as a while at all. Your condition suggests you'll keep trying until close() returns a non-negative value - however, what the code really is doing is retrying only if there's an interrupt. I strongly disagree that your while loop is more clear than a goto. Bending your code backwards to avoid using a goto isn't a good way of programming.

      Abigail

        bending a loop backwards ... isn't a good way of programming

        To me, it looks like you are bending an if backwards to create a loop. A while loop with a single iteration under most conditions is perfectly valid, a loop can even execute 0 times. Still valid. To me, the only number that matters is 'n', and n can take on any value, it doesn't matter. But I seriously doubt we will ever come to agreement on this (fair enough)... So I'll give up here.

        IMHO, using a goto to forge a loop isn't a good way of programming. Depends if you pray at the alter of Dijkstra (see link already posted below) or Knuth, I guess. If you have a online reference to the Knuth article, I'd like to read it to see how he justifies the theory. I'm not going to buy K&R or bother reading all of that MIX stuff, so please don't suggest that :)

      And I would make a small change on that to use a break and reduce the level of indentation.
      while (close(soc) < 0) { if (errno == EINTR) continue; perror("close"); exit 1; }
      I hope that's valid C. I don't really use it much.

        Here is why I did that though -- continue is just a goto by any other name. It leads to pollution of readable conditionals and loops just as the way a real goto causes an avoidance of conditionals and loops.

        The end result of using continue in long blocks of nested code is code that cannot be easily skimmed or traced .. a lesson learned by reading many many thousands of lines of bad C code. Especially when the level of nesting exceeds one, continue becomes a jump. Continue with block labels is even worse -- it's a PURE goto, only more politically correct. Someone will say "I can handle the power!", but I say "think of the children!".

        Also, your loop (by looking at indentation) implies that the perror() is in the main path of code execution, because it is masked by the indentation of the if -- which leads me to think "why is he executing exit periodically in a loop". My example avoids that by making the perror the exception rather than the rule. Subtle, but there was a method to my madness there. And of course, I am mad. There is no doubt about that.