News for hackers. Stuff that matters.
Re:Loop Exits and Structured Programming: Reopening the Deba... by chriswarbo on Monday June 12, 2017 @07:11PM (#14541879)
> The same is true when the name is "continue" or "throw": you know where in the program that goto leads

> Modern gotos aren't nearly as bad because they generally take a label rather than a number, and because their jump targets are often restricted to the immediate lexical environment.

That doesn't actually apply for your examples of "continue" or "throw" though. "continue" has no label, numeric or symbolic; its target is implicit from the lexical scope. "throw" has a sort of label (the type/class of the given value/exception), but its target is determined by the dynamic environment. Given a function like:

    function foo() {
      throw Bar;
    }
There is nothing in the lexical environment (i.e. the blocks within which it is written) that tells us where this will jump to. That information depends on what the stack looks like at the call site, which may be written by someone else, on the other side of the world, 20 years from now.
Re:Loop Exits and Structured Programming: Reopening the Deba... by lmkg on Monday June 12, 2017 @08:25PM (#14542173)
I apologize if I wasn't clear, I didn't mean to say that continue/throw are similar to modern gotos. Renamed gotos such as continue, break, and throw address the primary drawbacks of raw gotos. Unrelatedly, the gotos that one is likely to encounter in a modern-ish language like C or Common Lisp don't have all of those drawbacks anyways. My purpose was not to draw a comparison, merely to add some additional context for Dijkstra's original rants that may explain why the hard-line stance he took at the time makes a little less sense today.
Re:Loop Exits and Structured Programming: Reopening the Deba... by gpderetta on Tuesday June 13, 2017 @02:25AM (#14543175)
Technically the same thing is true for 'return'.
Re:Loop Exits and Structured Programming: Reopening the Deba... by chriswarbo on Tuesday June 13, 2017 @06:09AM (#14543820)
That's true, although 'return' will only pop one frame off the stack whilst 'throw' will keep going until it finds a handler. Hence 'return' has a more predictable/consistent behaviour, and less context-dependence.
Re:Loop Exits and Structured Programming: Reopening the Deba... by gpderetta on Tuesday June 13, 2017 @06:35AM (#14543887)
> although 'return' will only pop one frame off the stack

Unless it was a tail call...

Really, throw and return are quite similar, both invoke an externally provided continuation and abandon the current one.

Re:Loop Exits and Structured Programming: Reopening the Deba... by chriswarbo on Tuesday June 13, 2017 @07:26AM (#14544025)
Heh, I actually wrote something about continuations, then decided against it. I was going to say:

In a pure CPS setting, the caller's "only" responsibility is to give the right arguments (in scare quotes because getting a continuation right is usually trickier than the "plain" values usually given to functions).

In languages with functions, the caller is also responsible for handling/ignoring any return value and carrying out any subsequent computations, if the procedure returns.

In languages with exceptions, the caller is also responsible for handling/passing-on any exceptions.

Out of these three sorts of language, my current preference is for the second. It's probably fair to say that most procedures in a codebase will return a value (i.e. they're not continuations) and will not throw an exception (they're exceptional, after all). Hence it seems empirically desirable to allow `return`: it alters the semantics from a pure CPS scenario to one where we must always be vigilant that a procedure may return; but since most procedures (in such languages) return, that's not an edge case (in fact it's continuations, procedures without `return`, that are rare!); hence the benefits seem worth the cost.

When `throw` is introduced, we again must be vigilant when we're calling procedures. However, since most procedures don't `throw`, the benefit of having this ability is less than that of `return`. Also, since there may be many occurrences of `throw`, with different exception types, the cost of looking out for and handling these is greater than for `return`.

Hence my (current) opinion that `return` is very much a "good GOTO", whilst `throw` is a "bad GOTO" :)

Then we get `call-cc`... ;)

Re:Loop Exits and Structured Programming: Reopening the Deba... by gpderetta on Tuesday June 13, 2017 @10:15AM (#14544816)
The trick with throw is, of course, assuming that any procedure may potentially throw, except for a selected 'always succeeding' few. So avoid any non-local mutation and for those that are unavoidable take a transactional approach.

'call-cc', the control operator from hell that puts 'spaghetti' goto to shame.

Re:Loop Exits and Structured Programming: Reopening the Deba... by gpderetta on Tuesday June 13, 2017 @06:36AM (#14543894)
edit: but yes, of course I'm being pedantic.