4 comments

[ 3.6 ms ] story [ 20.8 ms ] thread
It seems like a complicated way to pretend you are not using goto while having semantics identical to goto. One advantage is that it is a block scope so if e.g. C++ had this, destructors could run, but this could also be supported with goto.
The semantics are much more restricted than goto. (a goto could always create a loop but situation indicators don't; a goto can jump between binding contours but situation indicators don't; etc.)

I think of it as an imperative way to pretend you're writing a tail-recursive nest with multiple base cases.

Does the following also have "semantics identical to goto"?

    // functional lands

    data EC = Situation1 | ... | SituationN

    case (Expr0) of
        Situation1 -> IOAction1
        ...
        SituationN -> IOActionN

    // imperative lands

    type Outcome int
    const Situation1 Outcome = iota, Situation2, ... SituationN

    var outcome Outcome
    for {
        ... { outcome = Situation1; break }
        ... { outcome = SituationN; break }
    }

    switch outcome {
    case Situation1:
        <statements1>
    ...
    case SituationN:
        <statementsN>
    }
I personally don't think so, Zahn's construct is merely a way to succinctly express such a switch in the control flow. In fact, Rust almost has it, with its loops being expressions.
Yes? This is making the code worse in order to dogmatically avoid goto.