Hacker News new | ask | show | jobs
by glassx 5020 days ago
I like the position of this C2 article on goto: http://c2.com/cgi/wiki?GotoConsideredHarmful

It argues that forward gotos (that work like continue, break, returns mid-function) don't contribute to spaghetti code, while backward gotos are more problematic.

2 comments

And yet backward goto is extremely useful. Consider this Java,

  redo: while(true) {
      for(Item x : xs)
          if(f(x))
              continue redo;
      break;
  }
With goto,

  redo:
  for(Item x : xs)
      if(f(x))
          goto redo;
Most people seem at first to balk at the goto, even though they're functionally identical, and the goto is much clearer and less error prone...
The article mentions that as well: "Backward gotos could be ok when it makes sense that your error case would repeat the last iteration"

Btw, in Ruby there are two keywords that are basically backward gotos: redo and retry.

That's the exact case where I saw it in the PostgreSQL code. Re-doing join pruning when a join was eliminated.
while (xs.Any(x => f(x))) { }

Pulling things out into other functions makes it even clearer.

Though yes, the goto is clearer than the labelled continue. I wouldn't necessarily agree that it's less error prone though.

Well, if we permit functional programming languages all the problems concerning imperative control flow magically go away...
I just used higher order functions to keep the example short, and I'd use them irl to avoid code repetition. The concept still applies without them:

    while (fTrueForAny(xs)) { }

    boolean fTrueForAny(List xs) {
      for (Item x : xs) {
        if (f(x)) {
          return true;
        }
      }

      return false;
    }
There isn't anything non-imperative about higher order functions.

    var externalDataStore = new ExternalDataStore()
    [1, 2, 3, 4].each(x => externalDataStore.store(x))
    externalDataStore.getItems().each(item => print(item))
Plenty of higher order functions, and plenty of non-functional, ordered, stateful, imperative code.
I would think that how localized the effect of the goto is would be far more important than whether it goes forward or back. Jumping back to the beginning of a function from the middle might be good. Jumping somewhere else, probably not so much.
Agreed, that wouldn't be too terrible, but then, again, I think that I always end up using a while loop for those cases when I have to "redo" stuff.