Proposal: Remove the "fallthrough" keyword

Is there a reason we cannot use labelled case statements?

    switch some_value {
    case .REFINED:
        if !validate(some_value) { return NULL }
        fallthrough base

    base: case .BASE:
        handle_enum_value();
    }

At least this is explicit now.

Yeah, maybe there's a more general language feature that could replace 'fallthrough' here. Instead of labelling cases, we could support a 'reswitch' statement that redispatches the switch to the case matching the operand:

    switch some_value {
    case .REFINED:
        if !validate(some_value) { return NULL }
        reswitch .BASE

    case .BASE:
        handle_enum_value();
    }

That should be easy to peephole to a proper fallthrough in constant cases, but would also nicely generalize to applications like interpreters, where it's often desirable to push the dispatch inline into the logic for better pipelining.

-Joe

···

On Dec 5, 2015, at 10:13 AM, David Owens II <david@owensd.io> wrote:

On Dec 5, 2015, at 10:04 AM, Vinicius Vendramini <vinivendra@gmail.com <mailto:vinivendra@gmail.com>> wrote:

I understand there might be some cases in which the syntax provided is indeed useful for experienced programmers writing their code. However, in almost all the examples here, I had to struggle to understand the logic behind the code. Not because it’s poorly written... probably because this syntax may be used for many different purposes, so it’s hard to get what exactly is the intent behind each use.

In Pierre’s latest example, for instance, it took me a few seconds to understand what was going on. I know it’s a simplified case, but it seems clearer to me to just write something like

if some_value == .Refined && !validate(some_value) {
  return NULL
}
handle_enum_value()

More complex cases make for a better argument for `switch`es, mainly because they avoid big `if` pyramids, but especially in those I feel the resulting code is significantly harder to understand.

On Dec 5, 2015, at 12:15 PM, Pierre Habouzit <phabouzit@apple.com <mailto:phabouzit@apple.com>> wrote:

On Dec 5, 2015, at 9:02 AM, Chris Lattner <clattner@apple.com <mailto:clattner@apple.com>> wrote:

On Dec 4, 2015, at 2:05 PM, jalkut@red-sweater.com <mailto:jalkut@red-sweater.com> wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

I’m not making an argument either way, but I want to point something out: there is a major difference between fallthrough vs ++/c-style-for. To someone who doesn’t know them, the later are "syntactic magic” with no reasonable way to decipher other than looking them up somewhere. The former is an English word whose meaning is obvious in context.

All I’m saying is that to a reader of code, the “badness” of ++ and c-style for loops is greater than the “badness" of fallthrough.

Given that Swift has the goal to also be a low level language, fallthrough is really useful for conciseness and readability.

in system programming C, I find myself writing things like this very often:

switch (some_value) {
case ENUM_VALUE_REFINED:
    if (validate(some_value)) {
        return NULL;
    }
    /* fallthrough */
case ENUM_VALUE_BASE:
    handle_enum_value();
    …
}

Where the swift equivalent would roughly be:

switch some_value {
case .REFINED:
    if !validate(some_value) { return NULL }
    fallthrough
case .BASE:
    handle_enum_value();
}

This is as readable as it gets and is a pattern that the libdispatch has in several places e.g.

Of course, you cannot fall through to arbitrary cases, so things like this C code cannot be done in swift:

switch (some_value) {
case ENUM_VALUE_REFINED_1:
    if (validate(some_value)) {
        return NULL;
    }
    goto base_value;
case ENUM_VALUE_REFINED_2:
    if (validate(some_value)) {
        return NULL;
    }
    goto base_value;

case ENUM_VALUE_BASE:
base_value:
    handle_enum_value();
    …
}

cannot be written in swift, despite also being quite useful.

Jumping between arbitrary points inside a switch is disgusting. jumping from label to label is useful and not harmful especially in swift where you can’t place code between the “switch” and the first case.

-Pierre

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Very much thinking out loud and not really the implications, I wonder if we might just use "continue" instead of "reswitch".

I very much like specifying what case to fall through into, no matter how we spell it.

- Steve

···

On Dec 5, 2015, at 4:45 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:
On Dec 4, 2015, at 11:37 PM, John Calsbeek <john.calsbeek+lists@gmail.com> wrote:
`fallthrough` is conceptually similar to `goto` in that both allow natural expression of concepts that exist at the instruction level but are otherwise difficult to express with nested control structures. `fallthrough` is perhaps slightly less objectionable because control flow remains local, but it has a similar role.

It is not particularly natural to write `switch` statements with `fallthrough` in the reverse order that can be seen in Duff’s Device and similar constructs (case 7 falls through to 6 which falls through to 5, etc.). It’s just because you know for certain that all the code in case 6 would be duplicated in case 7, so 7 can transfer into 6 without a jump instruction. Communicating that to the compiler without `fallthrough` requires deeply nested `if`s.

Right. One idea that I’ve always had for “fallthrough” is that we might parameterize it in the future; parameterized it would mean “repeat the switch with this new value”, so that unparameterized fallthrough would mean “repeat the switch with a notional value that ends up in the next case”. There’s a very common pattern in switches of deferring to another case that I’ve always found very awkward to write in C, and while sometimes there’s no choice but to extract a helper function, there’s a still-fairly-structural code pattern here that I think we can sensibly support.

On the other hand, there’s an argument that this is an inappropriate extension for “fallthrough” specifically, which is one reason we’ve never pursued it.

Oh, I see that Joe already brought this up, spelled “reswitch”.

John.

John.

One defense comes to mind: there is talk of Swift aiming at systems programming. Is writing a threaded interpreter loop within the potential scope of Swift? That’s a use case that could make use of both `fallthrough` and `goto` (computed goto, really).

switch op {
case LOAD_INDIRECT:
   in0 = memory[in1]
   fallthrough
case LOAD:
   out0 = memory[in0]
//...
}

I am personally interested in the prospect of a language that can scale up to high-level concepts and down to “portable assembler,” but I don’t know if that is the right direction for Swift’s evolution.

Cheers,
John

On Dec 4, 2015, at 2:42 PM, John McCall <rjmccall@apple.com> wrote:

On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin@sb.org> wrote:
It's not actually Duff's Device. Duff's Device relies on the fact that C switch statements don't actually introduce a new scope, and so it overlaps a switch with a do-while loop. This lets it only test the number of bytes once, to jump into the middle of the loop, and then it switches over to a while loop that decrements a counter every 8 instructions. Basically, it's a trick for manual loop unrolling that deals with non-multiple-of-8 counts efficiently.

To be pedantic, C switch statements do introduce a new scope. What Duff’s Device exploits is that switch is allowed to jump into (almost) arbitrary scopes, and cases can appear anywhere recursively inside a switch.

But your point that Swift’s switch requires cases to be at the top level within a switch and thus prevents the use of Duff’s Device is 100% correct.

John.

Steve's code is also an example of manual loop unrolling that deals with non-multiple-of-8 counts, but it has calculate the number of bytes on every iteration instead of once. It's a good example of one of the uses of `fallthrough`, it's just not Duff's Device. It's impossible to use Duff's Device in Swift.

-Kevin Ballard

On Fri, Dec 4, 2015, at 02:16 PM, Greg Titus wrote:
Streza’s source code is an example of Duff’s Device, which is a big place where switch fallthrough is arguably the cleanest way to do things and the reason why I’d personally prefer to keep it as part of the language.

On Dec 4, 2015, at 2:12 PM, Erica Sadun <erica@ericasadun.com> wrote:

Oh let it die, let it die. Any time I use fallthrough I find myself re-factoring to stop using it.

True fact: On all of gist.github.com, there are only 22 gist results for "fallthrough language:swift".
Half of those are people just testing out the feature. Most of the remaining ones are just complex cases:
case .Enum1, .Enum2:
expressed as
case .Enum1: fallthrough
case .Enum2:

And then there's streza: Base32.swift · GitHub I'm pretty sure that ponies were harmed in the production of whatever that last bit is.

On Dec 4, 2015, at 3:05 PM, jalkut@red-sweater.com wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

My understanding is this keyword is only used for the archaic seeming purpose of perpetuating C-style fallthrough from one switch statement to the subsequent one. The documentation hedges the use of this keyword in forbidding terms that make it clear its use is not encouraged. The presence of the keyword, while an improvement over C’s implicit fallthrough, is a mark of inelegance on an otherwise well-designed, opinionated implementation of swtich statements.

The ugliness of fallthrough’s C-style behavior even demands a caveat in the documentation:

"The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior."

To my mind, the caveat explains just what is wrong with fallthrough, both in C or Swift: coded that is clearly labeled with deliberate conditions can nonetheless be reached.

I quipped about this on Twitter, and the most common pushback I got seemed to be from people who either did not know about Swift’s support for comma-separated case statements, or harbored an aesthetic preference for clustering such cases together with fallthrough statements.

In my opinion, unless somebody can think of a strong defense for supporting intentional fallthrough in Swift, removing the keyword would be a move in the direction of minimizing the language’s complexity while also discouraging poor coding style in switch statements.

Thoughts?

Daniel

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Is there a reason we cannot use labelled case statements?

    switch some_value {
    case .REFINED:
        if !validate(some_value) { return NULL }
        fallthrough base

    base: case .BASE:
        handle_enum_value();
    }

At least this is explicit now.

Yeah, maybe there's a more general language feature that could replace 'fallthrough' here. Instead
of labelling cases, we could support a 'reswitch' statement that redispatches the switch to the case
matching the operand:

    switch some_value {
    case .REFINED:
        if !validate(some_value) { return NULL }
        reswitch .BASE

    case .BASE:
        handle_enum_value();
    }

We should just call a spade a spade and spell that "goto" ;-)

···

on Sat Dec 05 2015, jgroff@apple.com (Joe Groff) wrote:

On Dec 5, 2015, at 10:13 AM, David Owens II <david at owensd.io> wrote:

That should be easy to peephole to a proper fallthrough in constant cases, but would also nicely
generalize to applications like interpreters, where it's often desirable to push the dispatch inline
into the logic for better pipelining.

-Joe

On Dec 5, 2015, at 10:04 AM, Vinicius Vendramini <vinivendra at gmail.com <mailto:vinivendra at > gmail.com>> wrote:

I understand there might be some cases in which the syntax provided
is indeed useful for experienced programmers writing their
code. However, in almost all the examples here, I had to struggle
to understand the logic behind the code. Not because it’s poorly
written... probably because this syntax may be used for many
different purposes, so it’s hard to get what exactly is the intent
behind each use.

In Pierre’s latest example, for instance, it took me a few seconds
to understand what was going on. I know it’s a simplified case, but
it seems clearer to me to just write something like

if some_value == .Refined && !validate(some_value) {
  return NULL
}
handle_enum_value()

More complex cases make for a better argument for `switch`es,
mainly because they avoid big `if` pyramids, but especially in
those I feel the resulting code is significantly harder to
understand.

On Dec 5, 2015, at 12:15 PM, Pierre Habouzit <phabouzit at apple.com <mailto:phabouzit at apple.com>> wrote:

On Dec 5, 2015, at 9:02 AM, Chris Lattner <clattner at apple.com <mailto:clattner at apple.com>> wrote:

On Dec 4, 2015, at 2:05 PM, jalkut at red-sweater.com <mailto:jalkut at red-sweater.com> wrote:

In the spirit of some other proposals that remove C or C++ style
artifacts, what do folks think about the possibility of removing
the "fallthrough" keyword from the language?

I’m not making an argument either way, but I want to point
something out: there is a major difference between fallthrough vs
++/c-style-for. To someone who doesn’t know them, the later are
"syntactic magic” with no reasonable way to decipher other than
looking them up somewhere. The former is an English word whose
meaning is obvious in context.

All I’m saying is that to a reader of code, the “badness” of ++
and c-style for loops is greater than the “badness" of
fallthrough.

Given that Swift has the goal to also be a low level language, fallthrough is really useful for conciseness and readability.

in system programming C, I find myself writing things like this very often:

switch (some_value) {
case ENUM_VALUE_REFINED:
    if (validate(some_value)) {
        return NULL;
    }
    /* fallthrough */
case ENUM_VALUE_BASE:
    handle_enum_value();
    …
}

Where the swift equivalent would roughly be:

switch some_value {
case .REFINED:
    if !validate(some_value) { return NULL }
    fallthrough
case .BASE:
    handle_enum_value();
}

This is as readable as it gets and is a pattern that the libdispatch has in several places e.g.

Of course, you cannot fall through to arbitrary cases, so things like this C code cannot be done in swift:

switch (some_value) {
case ENUM_VALUE_REFINED_1:
    if (validate(some_value)) {
        return NULL;
    }
    goto base_value;
case ENUM_VALUE_REFINED_2:
    if (validate(some_value)) {
        return NULL;
    }
    goto base_value;

case ENUM_VALUE_BASE:
base_value:
    handle_enum_value();
    …
}

cannot be written in swift, despite also being quite useful.

Jumping between arbitrary points inside a switch is disgusting. jumping from label to label is useful and not harmful especially in swift where you can’t place code between the “switch” and the first case.

-Pierre

_______________________________________________
swift-evolution mailing list
swift-evolution at swift.org <mailto:swift-evolution at swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution at swift.org <mailto:swift-evolution at swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

<https://lists.swift.org/mailman/listinfo/swift-evolution&gt;

_______________________________________________
swift-evolution mailing list
swift-evolution at swift.org <mailto:swift-evolution at swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

<https://lists.swift.org/mailman/listinfo/swift-evolution&gt;
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<https://lists.swift.org/pipermail/swift-evolution/attachments/20151205/193d117e/attachment.html&gt;

--
-Dave

+1 for this idea, but I will prefer the reswitch keyword instead of overloading continue with a new syntax.

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

···

Sent from my iPad

On 06 Dec 2015, at 00:23, Steve Canon via swift-evolution <swift-evolution@swift.org> wrote:

Very much thinking out loud and not really the implications, I wonder if we might just use "continue" instead of "reswitch".

I very much like specifying what case to fall through into, no matter how we spell it.

- Steve

On Dec 5, 2015, at 4:45 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:
On Dec 4, 2015, at 11:37 PM, John Calsbeek <john.calsbeek+lists@gmail.com> wrote:
`fallthrough` is conceptually similar to `goto` in that both allow natural expression of concepts that exist at the instruction level but are otherwise difficult to express with nested control structures. `fallthrough` is perhaps slightly less objectionable because control flow remains local, but it has a similar role.

It is not particularly natural to write `switch` statements with `fallthrough` in the reverse order that can be seen in Duff’s Device and similar constructs (case 7 falls through to 6 which falls through to 5, etc.). It’s just because you know for certain that all the code in case 6 would be duplicated in case 7, so 7 can transfer into 6 without a jump instruction. Communicating that to the compiler without `fallthrough` requires deeply nested `if`s.

Right. One idea that I’ve always had for “fallthrough” is that we might parameterize it in the future; parameterized it would mean “repeat the switch with this new value”, so that unparameterized fallthrough would mean “repeat the switch with a notional value that ends up in the next case”. There’s a very common pattern in switches of deferring to another case that I’ve always found very awkward to write in C, and while sometimes there’s no choice but to extract a helper function, there’s a still-fairly-structural code pattern here that I think we can sensibly support.

On the other hand, there’s an argument that this is an inappropriate extension for “fallthrough” specifically, which is one reason we’ve never pursued it.

Oh, I see that Joe already brought this up, spelled “reswitch”.

John.

John.

One defense comes to mind: there is talk of Swift aiming at systems programming. Is writing a threaded interpreter loop within the potential scope of Swift? That’s a use case that could make use of both `fallthrough` and `goto` (computed goto, really).

switch op {
case LOAD_INDIRECT:
   in0 = memory[in1]
   fallthrough
case LOAD:
   out0 = memory[in0]
//...
}

I am personally interested in the prospect of a language that can scale up to high-level concepts and down to “portable assembler,” but I don’t know if that is the right direction for Swift’s evolution.

Cheers,
John

On Dec 4, 2015, at 2:42 PM, John McCall <rjmccall@apple.com> wrote:

On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin@sb.org> wrote:
It's not actually Duff's Device. Duff's Device relies on the fact that C switch statements don't actually introduce a new scope, and so it overlaps a switch with a do-while loop. This lets it only test the number of bytes once, to jump into the middle of the loop, and then it switches over to a while loop that decrements a counter every 8 instructions. Basically, it's a trick for manual loop unrolling that deals with non-multiple-of-8 counts efficiently.

To be pedantic, C switch statements do introduce a new scope. What Duff’s Device exploits is that switch is allowed to jump into (almost) arbitrary scopes, and cases can appear anywhere recursively inside a switch.

But your point that Swift’s switch requires cases to be at the top level within a switch and thus prevents the use of Duff’s Device is 100% correct.

John.

Steve's code is also an example of manual loop unrolling that deals with non-multiple-of-8 counts, but it has calculate the number of bytes on every iteration instead of once. It's a good example of one of the uses of `fallthrough`, it's just not Duff's Device. It's impossible to use Duff's Device in Swift.

-Kevin Ballard

On Fri, Dec 4, 2015, at 02:16 PM, Greg Titus wrote:
Streza’s source code is an example of Duff’s Device, which is a big place where switch fallthrough is arguably the cleanest way to do things and the reason why I’d personally prefer to keep it as part of the language.

On Dec 4, 2015, at 2:12 PM, Erica Sadun <erica@ericasadun.com> wrote:

Oh let it die, let it die. Any time I use fallthrough I find myself re-factoring to stop using it.

True fact: On all of gist.github.com, there are only 22 gist results for "fallthrough language:swift".
Half of those are people just testing out the feature. Most of the remaining ones are just complex cases:
case .Enum1, .Enum2:
expressed as
case .Enum1: fallthrough
case .Enum2:

And then there's streza: Base32.swift · GitHub I'm pretty sure that ponies were harmed in the production of whatever that last bit is.

On Dec 4, 2015, at 3:05 PM, jalkut@red-sweater.com wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

My understanding is this keyword is only used for the archaic seeming purpose of perpetuating C-style fallthrough from one switch statement to the subsequent one. The documentation hedges the use of this keyword in forbidding terms that make it clear its use is not encouraged. The presence of the keyword, while an improvement over C’s implicit fallthrough, is a mark of inelegance on an otherwise well-designed, opinionated implementation of swtich statements.

The ugliness of fallthrough’s C-style behavior even demands a caveat in the documentation:

"The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior."

To my mind, the caveat explains just what is wrong with fallthrough, both in C or Swift: coded that is clearly labeled with deliberate conditions can nonetheless be reached.

I quipped about this on Twitter, and the most common pushback I got seemed to be from people who either did not know about Swift’s support for comma-separated case statements, or harbored an aesthetic preference for clustering such cases together with fallthrough statements.

In my opinion, unless somebody can think of a strong defense for supporting intentional fallthrough in Swift, removing the keyword would be a move in the direction of minimizing the language’s complexity while also discouraging poor coding style in switch statements.

Thoughts?

Daniel

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Is there a reason we cannot use labelled case statements?

   switch some_value {
   case .REFINED:
       if !validate(some_value) { return NULL }
       fallthrough base

   base: case .BASE:
       handle_enum_value();
   }

At least this is explicit now.

Yeah, maybe there's a more general language feature that could replace 'fallthrough' here. Instead
of labelling cases, we could support a 'reswitch' statement that redispatches the switch to the case
matching the operand:

   switch some_value {
   case .REFINED:
       if !validate(some_value) { return NULL }
       reswitch .BASE

   case .BASE:
       handle_enum_value();
   }

We should just call a spade a spade and spell that "goto" ;-)

Cool by me. This does have the nice benefit over traditional 'goto' that each strand of spaghetti at least has a well-defined lexical scope, and a controlled way of passing state among scopes by pattern matching.

-Joe

···

On Jan 20, 2017, at 12:22 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:
on Sat Dec 05 2015, jgroff@apple.com (Joe Groff) wrote:

On Dec 5, 2015, at 10:13 AM, David Owens II <david at owensd.io> wrote:

That should be easy to peephole to a proper fallthrough in constant cases, but would also nicely
generalize to applications like interpreters, where it's often desirable to push the dispatch inline
into the logic for better pipelining.

-Joe

On Dec 5, 2015, at 10:04 AM, Vinicius Vendramini <vinivendra at gmail.com <mailto:vinivendra at >> gmail.com>> wrote:

I understand there might be some cases in which the syntax provided
is indeed useful for experienced programmers writing their
code. However, in almost all the examples here, I had to struggle
to understand the logic behind the code. Not because it’s poorly
written... probably because this syntax may be used for many
different purposes, so it’s hard to get what exactly is the intent
behind each use.

In Pierre’s latest example, for instance, it took me a few seconds
to understand what was going on. I know it’s a simplified case, but
it seems clearer to me to just write something like

if some_value == .Refined && !validate(some_value) {
  return NULL
}
handle_enum_value()

More complex cases make for a better argument for `switch`es,
mainly because they avoid big `if` pyramids, but especially in
those I feel the resulting code is significantly harder to
understand.

On Dec 5, 2015, at 12:15 PM, Pierre Habouzit <phabouzit at apple.com <mailto:phabouzit at apple.com>> wrote:

On Dec 5, 2015, at 9:02 AM, Chris Lattner <clattner at apple.com <mailto:clattner at apple.com>> wrote:

On Dec 4, 2015, at 2:05 PM, jalkut at red-sweater.com <mailto:jalkut at red-sweater.com> wrote:

In the spirit of some other proposals that remove C or C++ style
artifacts, what do folks think about the possibility of removing
the "fallthrough" keyword from the language?

I’m not making an argument either way, but I want to point
something out: there is a major difference between fallthrough vs
++/c-style-for. To someone who doesn’t know them, the later are
"syntactic magic” with no reasonable way to decipher other than
looking them up somewhere. The former is an English word whose
meaning is obvious in context.

All I’m saying is that to a reader of code, the “badness” of ++
and c-style for loops is greater than the “badness" of
fallthrough.

Given that Swift has the goal to also be a low level language, fallthrough is really useful for conciseness and readability.

in system programming C, I find myself writing things like this very often:

switch (some_value) {
case ENUM_VALUE_REFINED:
   if (validate(some_value)) {
       return NULL;
   }
   /* fallthrough */
case ENUM_VALUE_BASE:
   handle_enum_value();
   …
}

Where the swift equivalent would roughly be:

switch some_value {
case .REFINED:
   if !validate(some_value) { return NULL }
   fallthrough
case .BASE:
   handle_enum_value();
}

This is as readable as it gets and is a pattern that the libdispatch has in several places e.g.

Of course, you cannot fall through to arbitrary cases, so things like this C code cannot be done in swift:

switch (some_value) {
case ENUM_VALUE_REFINED_1:
   if (validate(some_value)) {
       return NULL;
   }
   goto base_value;
case ENUM_VALUE_REFINED_2:
   if (validate(some_value)) {
       return NULL;
   }
   goto base_value;

case ENUM_VALUE_BASE:
base_value:
   handle_enum_value();
   …
}

cannot be written in swift, despite also being quite useful.

Jumping between arbitrary points inside a switch is disgusting. jumping from label to label is useful and not harmful especially in swift where you can’t place code between the “switch” and the first case.

-Pierre

_______________________________________________
swift-evolution mailing list
swift-evolution at swift.org <mailto:swift-evolution at swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution at swift.org <mailto:swift-evolution at swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

<https://lists.swift.org/mailman/listinfo/swift-evolution&gt;

_______________________________________________
swift-evolution mailing list
swift-evolution at swift.org <mailto:swift-evolution at swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

<https://lists.swift.org/mailman/listinfo/swift-evolution&gt;
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<https://lists.swift.org/pipermail/swift-evolution/attachments/20151205/193d117e/attachment.html&gt;

--
-Dave

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Goto has traditionally been used for unstructured control flow, but this form is still fully structured. You cannot produce irreducible loops, jump into scopes, over declarations, etc.

-Chris

···

On Jan 20, 2017, at 12:22 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

Yeah, maybe there's a more general language feature that could replace 'fallthrough' here. Instead
of labelling cases, we could support a 'reswitch' statement that redispatches the switch to the case
matching the operand:

   switch some_value {
   case .REFINED:
       if !validate(some_value) { return NULL }
       reswitch .BASE

   case .BASE:
       handle_enum_value();
   }

We should just call a spade a spade and spell that "goto" ;-)

Detecting this in general is solving the halting problem, so such a check isn't actually feasible. One could warn when termination can't be proved, but making it a hard error would remove much of the usefulness for implementing interpreters.

- Steve

···

On Dec 6, 2015, at 4:52 AM, Jacopo Andrea Giola <swift-evolution@jacopo.giola.org>

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

tl;dr The fallthrough keyword, as far as I am aware, isn’t costing us anything; and has at least minimal utility, as I try to demonstrate.

Apologies for jumping into this thread at an awkward point, but I’ve only just now subscribed to this list.

I think the fallthrough keyword is useful in certain circumstances. I’ve also yet to see an example of where it creates a negative impact, either in code, optimization, or what have you. Other than “It’s like something in C, and C is old and busted” I’m unsure of the rationale for removing it. (Feel free to point me in the right direction.)

Consider the Planet enum from the documentation. One of the simplest way to define the number of a planet (i.e. its 1-based index in the ordering of planets wrt. distance from the sun) is using a switch and fall-through:

This technique is very extensible — for instance imagine computing the force induced by the gravity of the other planets on a particular planet. All that would need to change is the case statements.

Yes, you could write this by putting the planets into a list and mapping or folding (or looping) over that, but unless the compiler can “unroll” that construct, you’re paying for an allocation simply bc of your choice of control flow. But in fact, you could imagine generalizing this construct into the implementation of fold for the Planet type — low-overhead folds for monomorphic types seems like a pretty compelling an natural use case for fallthrough to me.

Thanks,
-Colin

···

On Dec 6, 2015, at 4:52 AM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org> wrote:

+1 for this idea, but I will prefer the reswitch keyword instead of overloading continue with a new syntax.

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

Sent from my iPad

On 06 Dec 2015, at 00:23, Steve Canon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Very much thinking out loud and not really the implications, I wonder if we might just use "continue" instead of "reswitch".

I very much like specifying what case to fall through into, no matter how we spell it.

- Steve

On Dec 5, 2015, at 4:45 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 4, 2015, at 11:37 PM, John Calsbeek <john.calsbeek+lists@gmail.com <mailto:john.calsbeek+lists@gmail.com>> wrote:
`fallthrough` is conceptually similar to `goto` in that both allow natural expression of concepts that exist at the instruction level but are otherwise difficult to express with nested control structures. `fallthrough` is perhaps slightly less objectionable because control flow remains local, but it has a similar role.

It is not particularly natural to write `switch` statements with `fallthrough` in the reverse order that can be seen in Duff’s Device and similar constructs (case 7 falls through to 6 which falls through to 5, etc.). It’s just because you know for certain that all the code in case 6 would be duplicated in case 7, so 7 can transfer into 6 without a jump instruction. Communicating that to the compiler without `fallthrough` requires deeply nested `if`s.

Right. One idea that I’ve always had for “fallthrough” is that we might parameterize it in the future; parameterized it would mean “repeat the switch with this new value”, so that unparameterized fallthrough would mean “repeat the switch with a notional value that ends up in the next case”. There’s a very common pattern in switches of deferring to another case that I’ve always found very awkward to write in C, and while sometimes there’s no choice but to extract a helper function, there’s a still-fairly-structural code pattern here that I think we can sensibly support.

On the other hand, there’s an argument that this is an inappropriate extension for “fallthrough” specifically, which is one reason we’ve never pursued it.

Oh, I see that Joe already brought this up, spelled “reswitch”.

John.

John.

One defense comes to mind: there is talk of Swift aiming at systems programming. Is writing a threaded interpreter loop within the potential scope of Swift? That’s a use case that could make use of both `fallthrough` and `goto` (computed goto, really).

switch op {
case LOAD_INDIRECT:
   in0 = memory[in1]
   fallthrough
case LOAD:
   out0 = memory[in0]
//...
}

I am personally interested in the prospect of a language that can scale up to high-level concepts and down to “portable assembler,” but I don’t know if that is the right direction for Swift’s evolution.

Cheers,
John

On Dec 4, 2015, at 2:42 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin@sb.org <mailto:kevin@sb.org>> wrote:
It's not actually Duff's Device. Duff's Device relies on the fact that C switch statements don't actually introduce a new scope, and so it overlaps a switch with a do-while loop. This lets it only test the number of bytes once, to jump into the middle of the loop, and then it switches over to a while loop that decrements a counter every 8 instructions. Basically, it's a trick for manual loop unrolling that deals with non-multiple-of-8 counts efficiently.

To be pedantic, C switch statements do introduce a new scope. What Duff’s Device exploits is that switch is allowed to jump into (almost) arbitrary scopes, and cases can appear anywhere recursively inside a switch.

But your point that Swift’s switch requires cases to be at the top level within a switch and thus prevents the use of Duff’s Device is 100% correct.

John.

Steve's code is also an example of manual loop unrolling that deals with non-multiple-of-8 counts, but it has calculate the number of bytes on every iteration instead of once. It's a good example of one of the uses of `fallthrough`, it's just not Duff's Device. It's impossible to use Duff's Device in Swift.

-Kevin Ballard

On Fri, Dec 4, 2015, at 02:16 PM, Greg Titus wrote:

Streza’s source code is an example of Duff’s Device, which is a big place where switch fallthrough is arguably the cleanest way to do things and the reason why I’d personally prefer to keep it as part of the language.

On Dec 4, 2015, at 2:12 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

Oh let it die, let it die. Any time I use fallthrough I find myself re-factoring to stop using it.

True fact: On all of gist.github.com <http://gist.github.com/&gt;, there are only 22 gist results for "fallthrough language:swift".
Half of those are people just testing out the feature. Most of the remaining ones are just complex cases:
case .Enum1, .Enum2:
expressed as
case .Enum1: fallthrough
case .Enum2:

And then there's streza: Base32.swift · GitHub I'm pretty sure that ponies were harmed in the production of whatever that last bit is.

On Dec 4, 2015, at 3:05 PM, jalkut@red-sweater.com <mailto:jalkut@red-sweater.com> wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

My understanding is this keyword is only used for the archaic seeming purpose of perpetuating C-style fallthrough from one switch statement to the subsequent one. The documentation hedges the use of this keyword in forbidding terms that make it clear its use is not encouraged. The presence of the keyword, while an improvement over C’s implicit fallthrough, is a mark of inelegance on an otherwise well-designed, opinionated implementation of swtich statements.

The ugliness of fallthrough’s C-style behavior even demands a caveat in the documentation:

"The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior."

To my mind, the caveat explains just what is wrong with fallthrough, both in C or Swift: coded that is clearly labeled with deliberate conditions can nonetheless be reached.

I quipped about this on Twitter, and the most common pushback I got seemed to be from people who either did not know about Swift’s support for comma-separated case statements, or harbored an aesthetic preference for clustering such cases together with fallthrough statements.

In my opinion, unless somebody can think of a strong defense for supporting intentional fallthrough in Swift, removing the keyword would be a move in the direction of minimizing the language’s complexity while also discouraging poor coding style in switch statements.

Thoughts?

Daniel

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

My dad always told me setjmp/longjmp "builds character".

What kind of character was never explained.

Russ

···

On Jan 20, 2017, at 12:45 PM, Joe Groff via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 20, 2017, at 12:22 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

on Sat Dec 05 2015, jgroff@apple.com (Joe Groff) wrote:

We should just call a spade a spade and spell that "goto" ;-)

Cool by me. This does have the nice benefit over traditional 'goto' that each strand of spaghetti at least has a well-defined lexical scope, and a controlled way of passing state among scopes by pattern matching.

-Joe

Yeah, maybe there's a more general language feature that could replace 'fallthrough' here. Instead
of labelling cases, we could support a 'reswitch' statement that redispatches the switch to the case
matching the operand:

   switch some_value {
   case .REFINED:
       if !validate(some_value) { return NULL }
       reswitch .BASE

   case .BASE:
       handle_enum_value();
   }

We should just call a spade a spade and spell that "goto" ;-)

Goto has traditionally been used for unstructured control flow, but this form is still fully structured. You cannot produce irreducible loops, jump into scopes, over declarations, etc.

It would be useful to know the technical definition of "structured." The fact is that there's a large category of sensible goto-like jumps that we probably want to allow and I see no advantage to giving them all distinct names. I don't believe users will distinguish them. We already have "break looplabel" and, aside from the label being in the wrong place, it's effectively a goto. It seems to me we should just have goto and either prohibit the troublesome uses or give them reasonable semantics.

I could live with "break" as well as "goto", but it feels a bit like it's pretending to be something it isn't, and there's the source compatibility problem with the label position.

-Dave

···

Sent from my iPad

On Jan 22, 2017, at 3:15 PM, Chris Lattner <clattner@nondot.org> wrote:

On Jan 20, 2017, at 12:22 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

Well, you caught me, I was thinking of a static analyzer check but for whatever reason my hands typed compiler check. Go figure.

In the static analyzer this check can be feasible? I know is not a memory leak, but at least he can see if the code flow inside a switch with reswitch statements will continue to go around on the same cases.
But this is only my wild guess, without a clue on what a static analyzer can do :)

- Jacopo

···

On 06 Dec 2015, at 18:16, Steve Canon <scanon@apple.com> wrote:

On Dec 6, 2015, at 4:52 AM, Jacopo Andrea Giola <swift-evolution@jacopo.giola.org>

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

Detecting this in general is solving the halting problem, so such a check isn't actually feasible. One could warn when termination can't be proved, but making it a hard error would remove much of the usefulness for implementing interpreters.

- Steve

Hi Colin,

the initial proposal was indeed to remove entirely the `fallthrough` keyword but many people expressed your similar concern and from that point the discussion was steered through an "enhancement" and better refinement of the keyword.

The new idea is to substitute the old keyword with "reswitch" passing the desired new value on which the switch is applied.
So something like this:

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .Two:
    // do something else
  default:
    // and so one
}

This new behaviour, IMO, is better suited for Swift because is more declarative of the developer intent and doesn't carry over unintentional misbehaviour.
Is more declarative because you are forced to state in which case you want to go, and even if the order of the switch’ cases will change in the future, you don't fall in the wrong case by mistake.

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // maybe this change is not made by you but by a messed up merge
  case .Two:
    // do something else
  default:
    // and so one
}

In this case if you are using the fallthrough keyboard your code is now broken by accident, and depending on what are you trying to do inside the cases you can have a hidden bug that your tests are not seeing right away.

Another advantage is that in this way you can made more cases fallthrough in the same one even if they are not one over each other

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two:
    // do something else that you may want to do for .One and .Two
  default:
    // and so one
}

I must say that this is a side effect that can be used to messed up the code flow in a way that is not intended, but is a new behaviour that gives more power to the switch statement.

The reswitch keyword in addition is not a mere fallthrough on the new case without doing the optional checking attached to it, but is intended to be a new call and all the check are executed.

switch (enum) {
  case .One:
    // do something
    x = 0;
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two where x > 0:
    // do something else that you may want to do for .One and .Two
    element = array
  default:
    // and so one
}
(I’m going by memory and by writing this snippets in the mail app directly, so the code must be incorrect in the syntax and for this I’m sorry).

In this case if enum is .One the only case that is executed is case .One and the code doesn’t fallthrough in the .Two case because we are made the where invalid by changing the x to a value less than 1.

Now I don’t remember who was the first one who mede this proposal, and I don’t know if he is working on a first draft to lay down the things better, but for me this can be a nice improvement and a neat break with the C-switch behaviour that Swift has trying to change from the very first beta disallowing the implicit fallthrough.

I can be completely wrong but I see the `fallthrough`keyword as a “temporary” implementation for ease the transition from Obj-C to Swift and is time to improve it and made the switch statement even more powerful.

- Jacopo

···

Sent from my iPad

On 06 Dec 2015, at 19:57, Colin Barrett via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

tl;dr The fallthrough keyword, as far as I am aware, isn’t costing us anything; and has at least minimal utility, as I try to demonstrate.

Apologies for jumping into this thread at an awkward point, but I’ve only just now subscribed to this list.

I think the fallthrough keyword is useful in certain circumstances. I’ve also yet to see an example of where it creates a negative impact, either in code, optimization, or what have you. Other than “It’s like something in C, and C is old and busted” I’m unsure of the rationale for removing it. (Feel free to point me in the right direction.)

Consider the Planet enum from the documentation. One of the simplest way to define the number of a planet (i.e. its 1-based index in the ordering of planets wrt. distance from the sun) is using a switch and fall-through:

fallthrough.swift · GitHub

This technique is very extensible — for instance imagine computing the force induced by the gravity of the other planets on a particular planet. All that would need to change is the case statements.

Yes, you could write this by putting the planets into a list and mapping or folding (or looping) over that, but unless the compiler can “unroll” that construct, you’re paying for an allocation simply bc of your choice of control flow. But in fact, you could imagine generalizing this construct into the implementation of fold for the Planet type — low-overhead folds for monomorphic types seems like a pretty compelling an natural use case for fallthrough to me.

Thanks,
-Colin

On Dec 6, 2015, at 4:52 AM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

+1 for this idea, but I will prefer the reswitch keyword instead of overloading continue with a new syntax.

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

Sent from my iPad

On 06 Dec 2015, at 00:23, Steve Canon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Very much thinking out loud and not really the implications, I wonder if we might just use "continue" instead of "reswitch".

I very much like specifying what case to fall through into, no matter how we spell it.

- Steve

On Dec 5, 2015, at 4:45 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 4, 2015, at 11:37 PM, John Calsbeek <john.calsbeek+lists@gmail.com <mailto:john.calsbeek+lists@gmail.com>> wrote:
`fallthrough` is conceptually similar to `goto` in that both allow natural expression of concepts that exist at the instruction level but are otherwise difficult to express with nested control structures. `fallthrough` is perhaps slightly less objectionable because control flow remains local, but it has a similar role.

It is not particularly natural to write `switch` statements with `fallthrough` in the reverse order that can be seen in Duff’s Device and similar constructs (case 7 falls through to 6 which falls through to 5, etc.). It’s just because you know for certain that all the code in case 6 would be duplicated in case 7, so 7 can transfer into 6 without a jump instruction. Communicating that to the compiler without `fallthrough` requires deeply nested `if`s.

Right. One idea that I’ve always had for “fallthrough” is that we might parameterize it in the future; parameterized it would mean “repeat the switch with this new value”, so that unparameterized fallthrough would mean “repeat the switch with a notional value that ends up in the next case”. There’s a very common pattern in switches of deferring to another case that I’ve always found very awkward to write in C, and while sometimes there’s no choice but to extract a helper function, there’s a still-fairly-structural code pattern here that I think we can sensibly support.

On the other hand, there’s an argument that this is an inappropriate extension for “fallthrough” specifically, which is one reason we’ve never pursued it.

Oh, I see that Joe already brought this up, spelled “reswitch”.

John.

John.

One defense comes to mind: there is talk of Swift aiming at systems programming. Is writing a threaded interpreter loop within the potential scope of Swift? That’s a use case that could make use of both `fallthrough` and `goto` (computed goto, really).

switch op {
case LOAD_INDIRECT:
   in0 = memory[in1]
   fallthrough
case LOAD:
   out0 = memory[in0]
//...
}

I am personally interested in the prospect of a language that can scale up to high-level concepts and down to “portable assembler,” but I don’t know if that is the right direction for Swift’s evolution.

Cheers,
John

On Dec 4, 2015, at 2:42 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin@sb.org <mailto:kevin@sb.org>> wrote:
It's not actually Duff's Device. Duff's Device relies on the fact that C switch statements don't actually introduce a new scope, and so it overlaps a switch with a do-while loop. This lets it only test the number of bytes once, to jump into the middle of the loop, and then it switches over to a while loop that decrements a counter every 8 instructions. Basically, it's a trick for manual loop unrolling that deals with non-multiple-of-8 counts efficiently.

To be pedantic, C switch statements do introduce a new scope. What Duff’s Device exploits is that switch is allowed to jump into (almost) arbitrary scopes, and cases can appear anywhere recursively inside a switch.

But your point that Swift’s switch requires cases to be at the top level within a switch and thus prevents the use of Duff’s Device is 100% correct.

John.

Steve's code is also an example of manual loop unrolling that deals with non-multiple-of-8 counts, but it has calculate the number of bytes on every iteration instead of once. It's a good example of one of the uses of `fallthrough`, it's just not Duff's Device. It's impossible to use Duff's Device in Swift.

-Kevin Ballard

On Fri, Dec 4, 2015, at 02:16 PM, Greg Titus wrote:

Streza’s source code is an example of Duff’s Device, which is a big place where switch fallthrough is arguably the cleanest way to do things and the reason why I’d personally prefer to keep it as part of the language.

On Dec 4, 2015, at 2:12 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

Oh let it die, let it die. Any time I use fallthrough I find myself re-factoring to stop using it.

True fact: On all of gist.github.com <http://gist.github.com/&gt;, there are only 22 gist results for "fallthrough language:swift".
Half of those are people just testing out the feature. Most of the remaining ones are just complex cases:
case .Enum1, .Enum2:
expressed as
case .Enum1: fallthrough
case .Enum2:

And then there's streza: Base32.swift · GitHub I'm pretty sure that ponies were harmed in the production of whatever that last bit is.

On Dec 4, 2015, at 3:05 PM, jalkut@red-sweater.com <mailto:jalkut@red-sweater.com> wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

My understanding is this keyword is only used for the archaic seeming purpose of perpetuating C-style fallthrough from one switch statement to the subsequent one. The documentation hedges the use of this keyword in forbidding terms that make it clear its use is not encouraged. The presence of the keyword, while an improvement over C’s implicit fallthrough, is a mark of inelegance on an otherwise well-designed, opinionated implementation of swtich statements.

The ugliness of fallthrough’s C-style behavior even demands a caveat in the documentation:

"The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior."

To my mind, the caveat explains just what is wrong with fallthrough, both in C or Swift: coded that is clearly labeled with deliberate conditions can nonetheless be reached.

I quipped about this on Twitter, and the most common pushback I got seemed to be from people who either did not know about Swift’s support for comma-separated case statements, or harbored an aesthetic preference for clustering such cases together with fallthrough statements.

In my opinion, unless somebody can think of a strong defense for supporting intentional fallthrough in Swift, removing the keyword would be a move in the direction of minimizing the language’s complexity while also discouraging poor coding style in switch statements.

Thoughts?

Daniel

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

I always assumed structured control flow means control only jumps to approved points, not arbitrary statements. Implicitly this is jumping out of a scope to a less-nested scope but never into a more-nested scope.

Swift takes this even further: you are limited to early exit of control flow. That’s a lot more restrictive than arbitrary goto.

Russ

···

On Jan 22, 2017, at 4:53 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org> wrote:

Sent from my iPad

On Jan 22, 2017, at 3:15 PM, Chris Lattner <clattner@nondot.org <mailto:clattner@nondot.org>> wrote:

On Jan 20, 2017, at 12:22 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Yeah, maybe there's a more general language feature that could replace 'fallthrough' here. Instead
of labelling cases, we could support a 'reswitch' statement that redispatches the switch to the case
matching the operand:

   switch some_value {
   case .REFINED:
       if !validate(some_value) { return NULL }
       reswitch .BASE

   case .BASE:
       handle_enum_value();
   }

We should just call a spade a spade and spell that "goto" ;-)

Goto has traditionally been used for unstructured control flow, but this form is still fully structured. You cannot produce irreducible loops, jump into scopes, over declarations, etc.

It would be useful to know the technical definition of "structured." The fact is that there's a large category of sensible goto-like jumps that we probably want to allow and I see no advantage to giving them all distinct names. I don't believe users will distinguish them. We already have "break looplabel" and, aside from the label being in the wrong place, it's effectively a goto. It seems to me we should just have goto and either prohibit the troublesome uses or give them reasonable semantics.

I could live with "break" as well as "goto", but it feels a bit like it's pretending to be something it isn't, and there's the source compatibility problem with the label position.

-Dave

To cope with the pattern matching cases, I would say that reswitch either has to:
1. Be limited specifically to a switch without pattern matching or enum values with associated data (such as Optional.Some). This would likely need to go beyond the limitations on fall through, which only limit value-binding patterns
2. Use instead of trying to treat the value of a reswitch as a label, treat it as a expression to re-execute the switch statement over:

switch(optionalThing) {
case .None:
  print(“assuming default value”)
  reswitch “default”
case .Some(let str):
  print(“processing value \(str)”);
}

This does however have non-intuitive behavior - when the second case statement is hit, “str" is no longer equal to "optionalThing!”. For that reason, one might find it clearer to require an explicit reassignment, effectively treating the switch as a loop:

switch(optionalThing) {
case .None:
  print(“assuming default value”)
  optionalThing = “default”
  reswitch
case .Some(let str):
  print(“processing value \(str)”);
}

The existing “continue” keyword seems a poor choice to recycle for this purpose; “repeat” or “retry” might be more appropriate than “reswitch"

-DW

···

On Dec 6, 2015, at 1:06 PM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org> wrote:

Hi Colin,

the initial proposal was indeed to remove entirely the `fallthrough` keyword but many people expressed your similar concern and from that point the discussion was steered through an "enhancement" and better refinement of the keyword.

The new idea is to substitute the old keyword with "reswitch" passing the desired new value on which the switch is applied.
So something like this:

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .Two:
    // do something else
  default:
    // and so one
}

This new behaviour, IMO, is better suited for Swift because is more declarative of the developer intent and doesn't carry over unintentional misbehaviour.
Is more declarative because you are forced to state in which case you want to go, and even if the order of the switch’ cases will change in the future, you don't fall in the wrong case by mistake.

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // maybe this change is not made by you but by a messed up merge
  case .Two:
    // do something else
  default:
    // and so one
}

In this case if you are using the fallthrough keyboard your code is now broken by accident, and depending on what are you trying to do inside the cases you can have a hidden bug that your tests are not seeing right away.

Another advantage is that in this way you can made more cases fallthrough in the same one even if they are not one over each other

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two:
    // do something else that you may want to do for .One and .Two
  default:
    // and so one
}

I must say that this is a side effect that can be used to messed up the code flow in a way that is not intended, but is a new behaviour that gives more power to the switch statement.

The reswitch keyword in addition is not a mere fallthrough on the new case without doing the optional checking attached to it, but is intended to be a new call and all the check are executed.

switch (enum) {
  case .One:
    // do something
    x = 0;
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two where x > 0:
    // do something else that you may want to do for .One and .Two
    element = array
  default:
    // and so one
}
(I’m going by memory and by writing this snippets in the mail app directly, so the code must be incorrect in the syntax and for this I’m sorry).

In this case if enum is .One the only case that is executed is case .One and the code doesn’t fallthrough in the .Two case because we are made the where invalid by changing the x to a value less than 1.

Now I don’t remember who was the first one who mede this proposal, and I don’t know if he is working on a first draft to lay down the things better, but for me this can be a nice improvement and a neat break with the C-switch behaviour that Swift has trying to change from the very first beta disallowing the implicit fallthrough.

I can be completely wrong but I see the `fallthrough`keyword as a “temporary” implementation for ease the transition from Obj-C to Swift and is time to improve it and made the switch statement even more powerful.

- Jacopo
Sent from my iPad

On 06 Dec 2015, at 19:57, Colin Barrett via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

tl;dr The fallthrough keyword, as far as I am aware, isn’t costing us anything; and has at least minimal utility, as I try to demonstrate.

Apologies for jumping into this thread at an awkward point, but I’ve only just now subscribed to this list.

I think the fallthrough keyword is useful in certain circumstances. I’ve also yet to see an example of where it creates a negative impact, either in code, optimization, or what have you. Other than “It’s like something in C, and C is old and busted” I’m unsure of the rationale for removing it. (Feel free to point me in the right direction.)

Consider the Planet enum from the documentation. One of the simplest way to define the number of a planet (i.e. its 1-based index in the ordering of planets wrt. distance from the sun) is using a switch and fall-through:

fallthrough.swift · GitHub

This technique is very extensible — for instance imagine computing the force induced by the gravity of the other planets on a particular planet. All that would need to change is the case statements.

Yes, you could write this by putting the planets into a list and mapping or folding (or looping) over that, but unless the compiler can “unroll” that construct, you’re paying for an allocation simply bc of your choice of control flow. But in fact, you could imagine generalizing this construct into the implementation of fold for the Planet type — low-overhead folds for monomorphic types seems like a pretty compelling an natural use case for fallthrough to me.

Thanks,
-Colin

On Dec 6, 2015, at 4:52 AM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

+1 for this idea, but I will prefer the reswitch keyword instead of overloading continue with a new syntax.

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

Sent from my iPad

On 06 Dec 2015, at 00:23, Steve Canon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Very much thinking out loud and not really the implications, I wonder if we might just use "continue" instead of "reswitch".

I very much like specifying what case to fall through into, no matter how we spell it.

- Steve

On Dec 5, 2015, at 4:45 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 4, 2015, at 11:37 PM, John Calsbeek <john.calsbeek+lists@gmail.com <mailto:john.calsbeek+lists@gmail.com>> wrote:
`fallthrough` is conceptually similar to `goto` in that both allow natural expression of concepts that exist at the instruction level but are otherwise difficult to express with nested control structures. `fallthrough` is perhaps slightly less objectionable because control flow remains local, but it has a similar role.

It is not particularly natural to write `switch` statements with `fallthrough` in the reverse order that can be seen in Duff’s Device and similar constructs (case 7 falls through to 6 which falls through to 5, etc.). It’s just because you know for certain that all the code in case 6 would be duplicated in case 7, so 7 can transfer into 6 without a jump instruction. Communicating that to the compiler without `fallthrough` requires deeply nested `if`s.

Right. One idea that I’ve always had for “fallthrough” is that we might parameterize it in the future; parameterized it would mean “repeat the switch with this new value”, so that unparameterized fallthrough would mean “repeat the switch with a notional value that ends up in the next case”. There’s a very common pattern in switches of deferring to another case that I’ve always found very awkward to write in C, and while sometimes there’s no choice but to extract a helper function, there’s a still-fairly-structural code pattern here that I think we can sensibly support.

On the other hand, there’s an argument that this is an inappropriate extension for “fallthrough” specifically, which is one reason we’ve never pursued it.

Oh, I see that Joe already brought this up, spelled “reswitch”.

John.

John.

One defense comes to mind: there is talk of Swift aiming at systems programming. Is writing a threaded interpreter loop within the potential scope of Swift? That’s a use case that could make use of both `fallthrough` and `goto` (computed goto, really).

switch op {
case LOAD_INDIRECT:
   in0 = memory[in1]
   fallthrough
case LOAD:
   out0 = memory[in0]
//...
}

I am personally interested in the prospect of a language that can scale up to high-level concepts and down to “portable assembler,” but I don’t know if that is the right direction for Swift’s evolution.

Cheers,
John

On Dec 4, 2015, at 2:42 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin@sb.org <mailto:kevin@sb.org>> wrote:
It's not actually Duff's Device. Duff's Device relies on the fact that C switch statements don't actually introduce a new scope, and so it overlaps a switch with a do-while loop. This lets it only test the number of bytes once, to jump into the middle of the loop, and then it switches over to a while loop that decrements a counter every 8 instructions. Basically, it's a trick for manual loop unrolling that deals with non-multiple-of-8 counts efficiently.

To be pedantic, C switch statements do introduce a new scope. What Duff’s Device exploits is that switch is allowed to jump into (almost) arbitrary scopes, and cases can appear anywhere recursively inside a switch.

But your point that Swift’s switch requires cases to be at the top level within a switch and thus prevents the use of Duff’s Device is 100% correct.

John.

Steve's code is also an example of manual loop unrolling that deals with non-multiple-of-8 counts, but it has calculate the number of bytes on every iteration instead of once. It's a good example of one of the uses of `fallthrough`, it's just not Duff's Device. It's impossible to use Duff's Device in Swift.

-Kevin Ballard

On Fri, Dec 4, 2015, at 02:16 PM, Greg Titus wrote:

Streza’s source code is an example of Duff’s Device, which is a big place where switch fallthrough is arguably the cleanest way to do things and the reason why I’d personally prefer to keep it as part of the language.

On Dec 4, 2015, at 2:12 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

Oh let it die, let it die. Any time I use fallthrough I find myself re-factoring to stop using it.

True fact: On all of gist.github.com <http://gist.github.com/&gt;, there are only 22 gist results for "fallthrough language:swift".
Half of those are people just testing out the feature. Most of the remaining ones are just complex cases:
case .Enum1, .Enum2:
expressed as
case .Enum1: fallthrough
case .Enum2:

And then there's streza: Base32.swift · GitHub I'm pretty sure that ponies were harmed in the production of whatever that last bit is.

On Dec 4, 2015, at 3:05 PM, jalkut@red-sweater.com <mailto:jalkut@red-sweater.com> wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

My understanding is this keyword is only used for the archaic seeming purpose of perpetuating C-style fallthrough from one switch statement to the subsequent one. The documentation hedges the use of this keyword in forbidding terms that make it clear its use is not encouraged. The presence of the keyword, while an improvement over C’s implicit fallthrough, is a mark of inelegance on an otherwise well-designed, opinionated implementation of swtich statements.

The ugliness of fallthrough’s C-style behavior even demands a caveat in the documentation:

"The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior."

To my mind, the caveat explains just what is wrong with fallthrough, both in C or Swift: coded that is clearly labeled with deliberate conditions can nonetheless be reached.

I quipped about this on Twitter, and the most common pushback I got seemed to be from people who either did not know about Swift’s support for comma-separated case statements, or harbored an aesthetic preference for clustering such cases together with fallthrough statements.

In my opinion, unless somebody can think of a strong defense for supporting intentional fallthrough in Swift, removing the keyword would be a move in the direction of minimizing the language’s complexity while also discouraging poor coding style in switch statements.

Thoughts?

Daniel

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Apologies, Jacopo, for missing the updated proposal, and thank you for your patience in summarizing it again.

I’ve only glanced through it but my concern here is that it introduces a whole class of new and creative “foot-guns" :) In particular, it allows this construction to loop arbitrarily and creatively, particularly in the case of associated values.

I’m not sure why not checking the case statement is considered a problem for the fallthrough keyword. Assuming it’s impossible to fallthrough to a case that introduces binders (what would they be bound to?), and that this is statically checked (both of which seem reasonable assumptions to me, although if I’m wrong feel free to correct me), isn’t it the entire point of the fallthrough keyword that it skips checking the case statement? I can understand how that might be somewhat confusing (and perhaps it should be documented less prominently) but I’m not sure how it’s a *problem*, exactly...

I think I’m still on the side of keeping fallthrough. What’s the downside of doing nothing? For instance in the case of ++ and -- those features complicate the design of a numerics library.

Thanks,
-Colin

···

On Dec 6, 2015, at 3:06 PM, Jacopo Andrea Giola <swift-evolution@jacopo.giola.org> wrote:

Hi Colin,

the initial proposal was indeed to remove entirely the `fallthrough` keyword but many people expressed your similar concern and from that point the discussion was steered through an "enhancement" and better refinement of the keyword.

The new idea is to substitute the old keyword with "reswitch" passing the desired new value on which the switch is applied.
So something like this:

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .Two:
    // do something else
  default:
    // and so one
}

This new behaviour, IMO, is better suited for Swift because is more declarative of the developer intent and doesn't carry over unintentional misbehaviour.
Is more declarative because you are forced to state in which case you want to go, and even if the order of the switch’ cases will change in the future, you don't fall in the wrong case by mistake.

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // maybe this change is not made by you but by a messed up merge
  case .Two:
    // do something else
  default:
    // and so one
}

In this case if you are using the fallthrough keyboard your code is now broken by accident, and depending on what are you trying to do inside the cases you can have a hidden bug that your tests are not seeing right away.

Another advantage is that in this way you can made more cases fallthrough in the same one even if they are not one over each other

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two:
    // do something else that you may want to do for .One and .Two
  default:
    // and so one
}

I must say that this is a side effect that can be used to messed up the code flow in a way that is not intended, but is a new behaviour that gives more power to the switch statement.

The reswitch keyword in addition is not a mere fallthrough on the new case without doing the optional checking attached to it, but is intended to be a new call and all the check are executed.

switch (enum) {
  case .One:
    // do something
    x = 0;
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two where x > 0:
    // do something else that you may want to do for .One and .Two
    element = array
  default:
    // and so one
}
(I’m going by memory and by writing this snippets in the mail app directly, so the code must be incorrect in the syntax and for this I’m sorry).

In this case if enum is .One the only case that is executed is case .One and the code doesn’t fallthrough in the .Two case because we are made the where invalid by changing the x to a value less than 1.

Now I don’t remember who was the first one who mede this proposal, and I don’t know if he is working on a first draft to lay down the things better, but for me this can be a nice improvement and a neat break with the C-switch behaviour that Swift has trying to change from the very first beta disallowing the implicit fallthrough.

I can be completely wrong but I see the `fallthrough`keyword as a “temporary” implementation for ease the transition from Obj-C to Swift and is time to improve it and made the switch statement even more powerful.

- Jacopo
Sent from my iPad

On 06 Dec 2015, at 19:57, Colin Barrett via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

tl;dr The fallthrough keyword, as far as I am aware, isn’t costing us anything; and has at least minimal utility, as I try to demonstrate.

Apologies for jumping into this thread at an awkward point, but I’ve only just now subscribed to this list.

I think the fallthrough keyword is useful in certain circumstances. I’ve also yet to see an example of where it creates a negative impact, either in code, optimization, or what have you. Other than “It’s like something in C, and C is old and busted” I’m unsure of the rationale for removing it. (Feel free to point me in the right direction.)

Consider the Planet enum from the documentation. One of the simplest way to define the number of a planet (i.e. its 1-based index in the ordering of planets wrt. distance from the sun) is using a switch and fall-through:

fallthrough.swift · GitHub

This technique is very extensible — for instance imagine computing the force induced by the gravity of the other planets on a particular planet. All that would need to change is the case statements.

Yes, you could write this by putting the planets into a list and mapping or folding (or looping) over that, but unless the compiler can “unroll” that construct, you’re paying for an allocation simply bc of your choice of control flow. But in fact, you could imagine generalizing this construct into the implementation of fold for the Planet type — low-overhead folds for monomorphic types seems like a pretty compelling an natural use case for fallthrough to me.

Thanks,
-Colin

On Dec 6, 2015, at 4:52 AM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

+1 for this idea, but I will prefer the reswitch keyword instead of overloading continue with a new syntax.

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

Sent from my iPad

On 06 Dec 2015, at 00:23, Steve Canon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Very much thinking out loud and not really the implications, I wonder if we might just use "continue" instead of "reswitch".

I very much like specifying what case to fall through into, no matter how we spell it.

- Steve

On Dec 5, 2015, at 4:45 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 4, 2015, at 11:37 PM, John Calsbeek <john.calsbeek+lists@gmail.com <mailto:john.calsbeek+lists@gmail.com>> wrote:
`fallthrough` is conceptually similar to `goto` in that both allow natural expression of concepts that exist at the instruction level but are otherwise difficult to express with nested control structures. `fallthrough` is perhaps slightly less objectionable because control flow remains local, but it has a similar role.

It is not particularly natural to write `switch` statements with `fallthrough` in the reverse order that can be seen in Duff’s Device and similar constructs (case 7 falls through to 6 which falls through to 5, etc.). It’s just because you know for certain that all the code in case 6 would be duplicated in case 7, so 7 can transfer into 6 without a jump instruction. Communicating that to the compiler without `fallthrough` requires deeply nested `if`s.

Right. One idea that I’ve always had for “fallthrough” is that we might parameterize it in the future; parameterized it would mean “repeat the switch with this new value”, so that unparameterized fallthrough would mean “repeat the switch with a notional value that ends up in the next case”. There’s a very common pattern in switches of deferring to another case that I’ve always found very awkward to write in C, and while sometimes there’s no choice but to extract a helper function, there’s a still-fairly-structural code pattern here that I think we can sensibly support.

On the other hand, there’s an argument that this is an inappropriate extension for “fallthrough” specifically, which is one reason we’ve never pursued it.

Oh, I see that Joe already brought this up, spelled “reswitch”.

John.

John.

One defense comes to mind: there is talk of Swift aiming at systems programming. Is writing a threaded interpreter loop within the potential scope of Swift? That’s a use case that could make use of both `fallthrough` and `goto` (computed goto, really).

switch op {
case LOAD_INDIRECT:
   in0 = memory[in1]
   fallthrough
case LOAD:
   out0 = memory[in0]
//...
}

I am personally interested in the prospect of a language that can scale up to high-level concepts and down to “portable assembler,” but I don’t know if that is the right direction for Swift’s evolution.

Cheers,
John

On Dec 4, 2015, at 2:42 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin@sb.org <mailto:kevin@sb.org>> wrote:
It's not actually Duff's Device. Duff's Device relies on the fact that C switch statements don't actually introduce a new scope, and so it overlaps a switch with a do-while loop. This lets it only test the number of bytes once, to jump into the middle of the loop, and then it switches over to a while loop that decrements a counter every 8 instructions. Basically, it's a trick for manual loop unrolling that deals with non-multiple-of-8 counts efficiently.

To be pedantic, C switch statements do introduce a new scope. What Duff’s Device exploits is that switch is allowed to jump into (almost) arbitrary scopes, and cases can appear anywhere recursively inside a switch.

But your point that Swift’s switch requires cases to be at the top level within a switch and thus prevents the use of Duff’s Device is 100% correct.

John.

Steve's code is also an example of manual loop unrolling that deals with non-multiple-of-8 counts, but it has calculate the number of bytes on every iteration instead of once. It's a good example of one of the uses of `fallthrough`, it's just not Duff's Device. It's impossible to use Duff's Device in Swift.

-Kevin Ballard

On Fri, Dec 4, 2015, at 02:16 PM, Greg Titus wrote:

Streza’s source code is an example of Duff’s Device, which is a big place where switch fallthrough is arguably the cleanest way to do things and the reason why I’d personally prefer to keep it as part of the language.

On Dec 4, 2015, at 2:12 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

Oh let it die, let it die. Any time I use fallthrough I find myself re-factoring to stop using it.

True fact: On all of gist.github.com <http://gist.github.com/&gt;, there are only 22 gist results for "fallthrough language:swift".
Half of those are people just testing out the feature. Most of the remaining ones are just complex cases:
case .Enum1, .Enum2:
expressed as
case .Enum1: fallthrough
case .Enum2:

And then there's streza: Base32.swift · GitHub I'm pretty sure that ponies were harmed in the production of whatever that last bit is.

On Dec 4, 2015, at 3:05 PM, jalkut@red-sweater.com <mailto:jalkut@red-sweater.com> wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

My understanding is this keyword is only used for the archaic seeming purpose of perpetuating C-style fallthrough from one switch statement to the subsequent one. The documentation hedges the use of this keyword in forbidding terms that make it clear its use is not encouraged. The presence of the keyword, while an improvement over C’s implicit fallthrough, is a mark of inelegance on an otherwise well-designed, opinionated implementation of swtich statements.

The ugliness of fallthrough’s C-style behavior even demands a caveat in the documentation:

"The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior."

To my mind, the caveat explains just what is wrong with fallthrough, both in C or Swift: coded that is clearly labeled with deliberate conditions can nonetheless be reached.

I quipped about this on Twitter, and the most common pushback I got seemed to be from people who either did not know about Swift’s support for comma-separated case statements, or harbored an aesthetic preference for clustering such cases together with fallthrough statements.

In my opinion, unless somebody can think of a strong defense for supporting intentional fallthrough in Swift, removing the keyword would be a move in the direction of minimizing the language’s complexity while also discouraging poor coding style in switch statements.

Thoughts?

Daniel

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Hi David,

sorry but I don’t understand what do you mean in your first point can you elaborate further?

2. your reswitch will throw a compile error, because you are try to call the switch with a different type, I imagine that to reswitch you can only pass a valid match to optionalThins so you have to pass a `String?` and yes, the proposal is to re execute the switch on the new value.

3. Your second example can’t be always valid because optionalThing can be a constant, I’m imagining that in the new switch execution optionalThing is being shadowed by the new value, but at the end of the execution optionalThing is the old value again.

···

On 06 Dec 2015, at 21:48, David Waite <david@alkaline-solutions.com> wrote:

To cope with the pattern matching cases, I would say that reswitch either has to:
1. Be limited specifically to a switch without pattern matching or enum values with associated data (such as Optional.Some). This would likely need to go beyond the limitations on fall through, which only limit value-binding patterns
2. Use instead of trying to treat the value of a reswitch as a label, treat it as a expression to re-execute the switch statement over:

switch(optionalThing) {
case .None:
  print(“assuming default value”)
  reswitch “default”
case .Some(let str):
  print(“processing value \(str)”);
}

This does however have non-intuitive behavior - when the second case statement is hit, “str" is no longer equal to "optionalThing!”. For that reason, one might find it clearer to require an explicit reassignment, effectively treating the switch as a loop:

switch(optionalThing) {
case .None:
  print(“assuming default value”)
  optionalThing = “default”
  reswitch
case .Some(let str):
  print(“processing value \(str)”);
}

The existing “continue” keyword seems a poor choice to recycle for this purpose; “repeat” or “retry” might be more appropriate than “reswitch"

-DW

On Dec 6, 2015, at 1:06 PM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi Colin,

the initial proposal was indeed to remove entirely the `fallthrough` keyword but many people expressed your similar concern and from that point the discussion was steered through an "enhancement" and better refinement of the keyword.

The new idea is to substitute the old keyword with "reswitch" passing the desired new value on which the switch is applied.
So something like this:

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .Two:
    // do something else
  default:
    // and so one
}

This new behaviour, IMO, is better suited for Swift because is more declarative of the developer intent and doesn't carry over unintentional misbehaviour.
Is more declarative because you are forced to state in which case you want to go, and even if the order of the switch’ cases will change in the future, you don't fall in the wrong case by mistake.

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // maybe this change is not made by you but by a messed up merge
  case .Two:
    // do something else
  default:
    // and so one
}

In this case if you are using the fallthrough keyboard your code is now broken by accident, and depending on what are you trying to do inside the cases you can have a hidden bug that your tests are not seeing right away.

Another advantage is that in this way you can made more cases fallthrough in the same one even if they are not one over each other

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two:
    // do something else that you may want to do for .One and .Two
  default:
    // and so one
}

I must say that this is a side effect that can be used to messed up the code flow in a way that is not intended, but is a new behaviour that gives more power to the switch statement.

The reswitch keyword in addition is not a mere fallthrough on the new case without doing the optional checking attached to it, but is intended to be a new call and all the check are executed.

switch (enum) {
  case .One:
    // do something
    x = 0;
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two where x > 0:
    // do something else that you may want to do for .One and .Two
    element = array
  default:
    // and so one
}
(I’m going by memory and by writing this snippets in the mail app directly, so the code must be incorrect in the syntax and for this I’m sorry).

In this case if enum is .One the only case that is executed is case .One and the code doesn’t fallthrough in the .Two case because we are made the where invalid by changing the x to a value less than 1.

Now I don’t remember who was the first one who mede this proposal, and I don’t know if he is working on a first draft to lay down the things better, but for me this can be a nice improvement and a neat break with the C-switch behaviour that Swift has trying to change from the very first beta disallowing the implicit fallthrough.

I can be completely wrong but I see the `fallthrough`keyword as a “temporary” implementation for ease the transition from Obj-C to Swift and is time to improve it and made the switch statement even more powerful.

- Jacopo
Sent from my iPad

On 06 Dec 2015, at 19:57, Colin Barrett via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

tl;dr The fallthrough keyword, as far as I am aware, isn’t costing us anything; and has at least minimal utility, as I try to demonstrate.

Apologies for jumping into this thread at an awkward point, but I’ve only just now subscribed to this list.

I think the fallthrough keyword is useful in certain circumstances. I’ve also yet to see an example of where it creates a negative impact, either in code, optimization, or what have you. Other than “It’s like something in C, and C is old and busted” I’m unsure of the rationale for removing it. (Feel free to point me in the right direction.)

Consider the Planet enum from the documentation. One of the simplest way to define the number of a planet (i.e. its 1-based index in the ordering of planets wrt. distance from the sun) is using a switch and fall-through:

fallthrough.swift · GitHub

This technique is very extensible — for instance imagine computing the force induced by the gravity of the other planets on a particular planet. All that would need to change is the case statements.

Yes, you could write this by putting the planets into a list and mapping or folding (or looping) over that, but unless the compiler can “unroll” that construct, you’re paying for an allocation simply bc of your choice of control flow. But in fact, you could imagine generalizing this construct into the implementation of fold for the Planet type — low-overhead folds for monomorphic types seems like a pretty compelling an natural use case for fallthrough to me.

Thanks,
-Colin

On Dec 6, 2015, at 4:52 AM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

+1 for this idea, but I will prefer the reswitch keyword instead of overloading continue with a new syntax.

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

Sent from my iPad

On 06 Dec 2015, at 00:23, Steve Canon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Very much thinking out loud and not really the implications, I wonder if we might just use "continue" instead of "reswitch".

I very much like specifying what case to fall through into, no matter how we spell it.

- Steve

On Dec 5, 2015, at 4:45 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 4, 2015, at 11:37 PM, John Calsbeek <john.calsbeek+lists@gmail.com <mailto:john.calsbeek+lists@gmail.com>> wrote:
`fallthrough` is conceptually similar to `goto` in that both allow natural expression of concepts that exist at the instruction level but are otherwise difficult to express with nested control structures. `fallthrough` is perhaps slightly less objectionable because control flow remains local, but it has a similar role.

It is not particularly natural to write `switch` statements with `fallthrough` in the reverse order that can be seen in Duff’s Device and similar constructs (case 7 falls through to 6 which falls through to 5, etc.). It’s just because you know for certain that all the code in case 6 would be duplicated in case 7, so 7 can transfer into 6 without a jump instruction. Communicating that to the compiler without `fallthrough` requires deeply nested `if`s.

Right. One idea that I’ve always had for “fallthrough” is that we might parameterize it in the future; parameterized it would mean “repeat the switch with this new value”, so that unparameterized fallthrough would mean “repeat the switch with a notional value that ends up in the next case”. There’s a very common pattern in switches of deferring to another case that I’ve always found very awkward to write in C, and while sometimes there’s no choice but to extract a helper function, there’s a still-fairly-structural code pattern here that I think we can sensibly support.

On the other hand, there’s an argument that this is an inappropriate extension for “fallthrough” specifically, which is one reason we’ve never pursued it.

Oh, I see that Joe already brought this up, spelled “reswitch”.

John.

John.

One defense comes to mind: there is talk of Swift aiming at systems programming. Is writing a threaded interpreter loop within the potential scope of Swift? That’s a use case that could make use of both `fallthrough` and `goto` (computed goto, really).

switch op {
case LOAD_INDIRECT:
   in0 = memory[in1]
   fallthrough
case LOAD:
   out0 = memory[in0]
//...
}

I am personally interested in the prospect of a language that can scale up to high-level concepts and down to “portable assembler,” but I don’t know if that is the right direction for Swift’s evolution.

Cheers,
John

On Dec 4, 2015, at 2:42 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin@sb.org <mailto:kevin@sb.org>> wrote:
It's not actually Duff's Device. Duff's Device relies on the fact that C switch statements don't actually introduce a new scope, and so it overlaps a switch with a do-while loop. This lets it only test the number of bytes once, to jump into the middle of the loop, and then it switches over to a while loop that decrements a counter every 8 instructions. Basically, it's a trick for manual loop unrolling that deals with non-multiple-of-8 counts efficiently.

To be pedantic, C switch statements do introduce a new scope. What Duff’s Device exploits is that switch is allowed to jump into (almost) arbitrary scopes, and cases can appear anywhere recursively inside a switch.

But your point that Swift’s switch requires cases to be at the top level within a switch and thus prevents the use of Duff’s Device is 100% correct.

John.

Steve's code is also an example of manual loop unrolling that deals with non-multiple-of-8 counts, but it has calculate the number of bytes on every iteration instead of once. It's a good example of one of the uses of `fallthrough`, it's just not Duff's Device. It's impossible to use Duff's Device in Swift.

-Kevin Ballard

On Fri, Dec 4, 2015, at 02:16 PM, Greg Titus wrote:

Streza’s source code is an example of Duff’s Device, which is a big place where switch fallthrough is arguably the cleanest way to do things and the reason why I’d personally prefer to keep it as part of the language.

On Dec 4, 2015, at 2:12 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

Oh let it die, let it die. Any time I use fallthrough I find myself re-factoring to stop using it.

True fact: On all of gist.github.com <http://gist.github.com/&gt;, there are only 22 gist results for "fallthrough language:swift".
Half of those are people just testing out the feature. Most of the remaining ones are just complex cases:
case .Enum1, .Enum2:
expressed as
case .Enum1: fallthrough
case .Enum2:

And then there's streza: Base32.swift · GitHub I'm pretty sure that ponies were harmed in the production of whatever that last bit is.

On Dec 4, 2015, at 3:05 PM, jalkut@red-sweater.com <mailto:jalkut@red-sweater.com> wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

My understanding is this keyword is only used for the archaic seeming purpose of perpetuating C-style fallthrough from one switch statement to the subsequent one. The documentation hedges the use of this keyword in forbidding terms that make it clear its use is not encouraged. The presence of the keyword, while an improvement over C’s implicit fallthrough, is a mark of inelegance on an otherwise well-designed, opinionated implementation of swtich statements.

The ugliness of fallthrough’s C-style behavior even demands a caveat in the documentation:

"The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior."

To my mind, the caveat explains just what is wrong with fallthrough, both in C or Swift: coded that is clearly labeled with deliberate conditions can nonetheless be reached.

I quipped about this on Twitter, and the most common pushback I got seemed to be from people who either did not know about Swift’s support for comma-separated case statements, or harbored an aesthetic preference for clustering such cases together with fallthrough statements.

In my opinion, unless somebody can think of a strong defense for supporting intentional fallthrough in Swift, removing the keyword would be a move in the direction of minimizing the language’s complexity while also discouraging poor coding style in switch statements.

Thoughts?

Daniel

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Yes, I’m aware that at this time the reswitch can be abused and maybe can be better refined to disallow such cases.

Checking the case statement is not a problem by itself, but can be a problem if is coupled with a where clause that is not true when you fallthrought.

I’ve written a really bad draft here Draft for changing the fallthorught keyword in Swift language · GitHub
If anyone wants to jump in and elaborate further is welcome. I will try to stay on par with this thread but I’m really bad at writing so every help is welcome.

And if I remember correctly Daniel Jakult was the first one to made this proposal so if he wants to take on and then made the official proposal has every right to do so and I will be very glad if my gist can be a first reference :)

- Jacopo

···

On 06 Dec 2015, at 21:52, Colin Barrett <colin@springsandstruts.com> wrote:

Apologies, Jacopo, for missing the updated proposal, and thank you for your patience in summarizing it again.

I’ve only glanced through it but my concern here is that it introduces a whole class of new and creative “foot-guns" :) In particular, it allows this construction to loop arbitrarily and creatively, particularly in the case of associated values.

I’m not sure why not checking the case statement is considered a problem for the fallthrough keyword. Assuming it’s impossible to fallthrough to a case that introduces binders (what would they be bound to?), and that this is statically checked (both of which seem reasonable assumptions to me, although if I’m wrong feel free to correct me), isn’t it the entire point of the fallthrough keyword that it skips checking the case statement? I can understand how that might be somewhat confusing (and perhaps it should be documented less prominently) but I’m not sure how it’s a *problem*, exactly...

I think I’m still on the side of keeping fallthrough. What’s the downside of doing nothing? For instance in the case of ++ and -- those features complicate the design of a numerics library.

Thanks,
-Colin

On Dec 6, 2015, at 3:06 PM, Jacopo Andrea Giola <swift-evolution@jacopo.giola.org <mailto:swift-evolution@jacopo.giola.org>> wrote:

Hi Colin,

the initial proposal was indeed to remove entirely the `fallthrough` keyword but many people expressed your similar concern and from that point the discussion was steered through an "enhancement" and better refinement of the keyword.

The new idea is to substitute the old keyword with "reswitch" passing the desired new value on which the switch is applied.
So something like this:

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .Two:
    // do something else
  default:
    // and so one
}

This new behaviour, IMO, is better suited for Swift because is more declarative of the developer intent and doesn't carry over unintentional misbehaviour.
Is more declarative because you are forced to state in which case you want to go, and even if the order of the switch’ cases will change in the future, you don't fall in the wrong case by mistake.

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // maybe this change is not made by you but by a messed up merge
  case .Two:
    // do something else
  default:
    // and so one
}

In this case if you are using the fallthrough keyboard your code is now broken by accident, and depending on what are you trying to do inside the cases you can have a hidden bug that your tests are not seeing right away.

Another advantage is that in this way you can made more cases fallthrough in the same one even if they are not one over each other

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two:
    // do something else that you may want to do for .One and .Two
  default:
    // and so one
}

I must say that this is a side effect that can be used to messed up the code flow in a way that is not intended, but is a new behaviour that gives more power to the switch statement.

The reswitch keyword in addition is not a mere fallthrough on the new case without doing the optional checking attached to it, but is intended to be a new call and all the check are executed.

switch (enum) {
  case .One:
    // do something
    x = 0;
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two where x > 0:
    // do something else that you may want to do for .One and .Two
    element = array
  default:
    // and so one
}
(I’m going by memory and by writing this snippets in the mail app directly, so the code must be incorrect in the syntax and for this I’m sorry).

In this case if enum is .One the only case that is executed is case .One and the code doesn’t fallthrough in the .Two case because we are made the where invalid by changing the x to a value less than 1.

Now I don’t remember who was the first one who mede this proposal, and I don’t know if he is working on a first draft to lay down the things better, but for me this can be a nice improvement and a neat break with the C-switch behaviour that Swift has trying to change from the very first beta disallowing the implicit fallthrough.

I can be completely wrong but I see the `fallthrough`keyword as a “temporary” implementation for ease the transition from Obj-C to Swift and is time to improve it and made the switch statement even more powerful.

- Jacopo
Sent from my iPad

On 06 Dec 2015, at 19:57, Colin Barrett via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

tl;dr The fallthrough keyword, as far as I am aware, isn’t costing us anything; and has at least minimal utility, as I try to demonstrate.

Apologies for jumping into this thread at an awkward point, but I’ve only just now subscribed to this list.

I think the fallthrough keyword is useful in certain circumstances. I’ve also yet to see an example of where it creates a negative impact, either in code, optimization, or what have you. Other than “It’s like something in C, and C is old and busted” I’m unsure of the rationale for removing it. (Feel free to point me in the right direction.)

Consider the Planet enum from the documentation. One of the simplest way to define the number of a planet (i.e. its 1-based index in the ordering of planets wrt. distance from the sun) is using a switch and fall-through:

fallthrough.swift · GitHub

This technique is very extensible — for instance imagine computing the force induced by the gravity of the other planets on a particular planet. All that would need to change is the case statements.

Yes, you could write this by putting the planets into a list and mapping or folding (or looping) over that, but unless the compiler can “unroll” that construct, you’re paying for an allocation simply bc of your choice of control flow. But in fact, you could imagine generalizing this construct into the implementation of fold for the Planet type — low-overhead folds for monomorphic types seems like a pretty compelling an natural use case for fallthrough to me.

Thanks,
-Colin

On Dec 6, 2015, at 4:52 AM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

+1 for this idea, but I will prefer the reswitch keyword instead of overloading continue with a new syntax.

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

Sent from my iPad

On 06 Dec 2015, at 00:23, Steve Canon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Very much thinking out loud and not really the implications, I wonder if we might just use "continue" instead of "reswitch".

I very much like specifying what case to fall through into, no matter how we spell it.

- Steve

On Dec 5, 2015, at 4:45 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 4, 2015, at 11:37 PM, John Calsbeek <john.calsbeek+lists@gmail.com <mailto:john.calsbeek+lists@gmail.com>> wrote:
`fallthrough` is conceptually similar to `goto` in that both allow natural expression of concepts that exist at the instruction level but are otherwise difficult to express with nested control structures. `fallthrough` is perhaps slightly less objectionable because control flow remains local, but it has a similar role.

It is not particularly natural to write `switch` statements with `fallthrough` in the reverse order that can be seen in Duff’s Device and similar constructs (case 7 falls through to 6 which falls through to 5, etc.). It’s just because you know for certain that all the code in case 6 would be duplicated in case 7, so 7 can transfer into 6 without a jump instruction. Communicating that to the compiler without `fallthrough` requires deeply nested `if`s.

Right. One idea that I’ve always had for “fallthrough” is that we might parameterize it in the future; parameterized it would mean “repeat the switch with this new value”, so that unparameterized fallthrough would mean “repeat the switch with a notional value that ends up in the next case”. There’s a very common pattern in switches of deferring to another case that I’ve always found very awkward to write in C, and while sometimes there’s no choice but to extract a helper function, there’s a still-fairly-structural code pattern here that I think we can sensibly support.

On the other hand, there’s an argument that this is an inappropriate extension for “fallthrough” specifically, which is one reason we’ve never pursued it.

Oh, I see that Joe already brought this up, spelled “reswitch”.

John.

John.

One defense comes to mind: there is talk of Swift aiming at systems programming. Is writing a threaded interpreter loop within the potential scope of Swift? That’s a use case that could make use of both `fallthrough` and `goto` (computed goto, really).

switch op {
case LOAD_INDIRECT:
   in0 = memory[in1]
   fallthrough
case LOAD:
   out0 = memory[in0]
//...
}

I am personally interested in the prospect of a language that can scale up to high-level concepts and down to “portable assembler,” but I don’t know if that is the right direction for Swift’s evolution.

Cheers,
John

On Dec 4, 2015, at 2:42 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin@sb.org <mailto:kevin@sb.org>> wrote:
It's not actually Duff's Device. Duff's Device relies on the fact that C switch statements don't actually introduce a new scope, and so it overlaps a switch with a do-while loop. This lets it only test the number of bytes once, to jump into the middle of the loop, and then it switches over to a while loop that decrements a counter every 8 instructions. Basically, it's a trick for manual loop unrolling that deals with non-multiple-of-8 counts efficiently.

To be pedantic, C switch statements do introduce a new scope. What Duff’s Device exploits is that switch is allowed to jump into (almost) arbitrary scopes, and cases can appear anywhere recursively inside a switch.

But your point that Swift’s switch requires cases to be at the top level within a switch and thus prevents the use of Duff’s Device is 100% correct.

John.

Steve's code is also an example of manual loop unrolling that deals with non-multiple-of-8 counts, but it has calculate the number of bytes on every iteration instead of once. It's a good example of one of the uses of `fallthrough`, it's just not Duff's Device. It's impossible to use Duff's Device in Swift.

-Kevin Ballard

On Fri, Dec 4, 2015, at 02:16 PM, Greg Titus wrote:

Streza’s source code is an example of Duff’s Device, which is a big place where switch fallthrough is arguably the cleanest way to do things and the reason why I’d personally prefer to keep it as part of the language.

On Dec 4, 2015, at 2:12 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

Oh let it die, let it die. Any time I use fallthrough I find myself re-factoring to stop using it.

True fact: On all of gist.github.com <http://gist.github.com/&gt;, there are only 22 gist results for "fallthrough language:swift".
Half of those are people just testing out the feature. Most of the remaining ones are just complex cases:
case .Enum1, .Enum2:
expressed as
case .Enum1: fallthrough
case .Enum2:

And then there's streza: Base32.swift · GitHub I'm pretty sure that ponies were harmed in the production of whatever that last bit is.

On Dec 4, 2015, at 3:05 PM, jalkut@red-sweater.com <mailto:jalkut@red-sweater.com> wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

My understanding is this keyword is only used for the archaic seeming purpose of perpetuating C-style fallthrough from one switch statement to the subsequent one. The documentation hedges the use of this keyword in forbidding terms that make it clear its use is not encouraged. The presence of the keyword, while an improvement over C’s implicit fallthrough, is a mark of inelegance on an otherwise well-designed, opinionated implementation of swtich statements.

The ugliness of fallthrough’s C-style behavior even demands a caveat in the documentation:

"The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior."

To my mind, the caveat explains just what is wrong with fallthrough, both in C or Swift: coded that is clearly labeled with deliberate conditions can nonetheless be reached.

I quipped about this on Twitter, and the most common pushback I got seemed to be from people who either did not know about Swift’s support for comma-separated case statements, or harbored an aesthetic preference for clustering such cases together with fallthrough statements.

In my opinion, unless somebody can think of a strong defense for supporting intentional fallthrough in Swift, removing the keyword would be a move in the direction of minimizing the language’s complexity while also discouraging poor coding style in switch statements.

Thoughts?

Daniel

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

To cope with the pattern matching cases, I would say that reswitch either has to:
1. Be limited specifically to a switch without pattern matching or enum values with associated data (such as Optional.Some). This would likely need to go beyond the limitations on fall through, which only limit value-binding patterns
2. Use instead of trying to treat the value of a reswitch as a label, treat it as a expression to re-execute the switch statement over:

switch(optionalThing) {
case .None:
  print(“assuming default value”)
  reswitch “default”
case .Some(let str):
  print(“processing value \(str)”);
}

This does however have non-intuitive behavior - when the second case statement is hit, “str" is no longer equal to "optionalThing!”. For that reason, one might find it clearer to require an explicit reassignment, effectively treating the switch as a loop:

switch(optionalThing) {
case .None:
  print(“assuming default value”)
  optionalThing = “default”
  reswitch
case .Some(let str):
  print(“processing value \(str)”);
}

Maybe it's just me, but this is the behavior I'd expect.

The existing “continue” keyword seems a poor choice to recycle for this purpose; “repeat” or “retry” might be more appropriate than “reswitch"

Agreed that this ought to be a distinct keyword.

-Joe

···

On Dec 6, 2015, at 12:48 PM, David Waite via swift-evolution <swift-evolution@swift.org> wrote:

-DW

On Dec 6, 2015, at 1:06 PM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Hi Colin,

the initial proposal was indeed to remove entirely the `fallthrough` keyword but many people expressed your similar concern and from that point the discussion was steered through an "enhancement" and better refinement of the keyword.

The new idea is to substitute the old keyword with "reswitch" passing the desired new value on which the switch is applied.
So something like this:

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .Two:
    // do something else
  default:
    // and so one
}

This new behaviour, IMO, is better suited for Swift because is more declarative of the developer intent and doesn't carry over unintentional misbehaviour.
Is more declarative because you are forced to state in which case you want to go, and even if the order of the switch’ cases will change in the future, you don't fall in the wrong case by mistake.

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // maybe this change is not made by you but by a messed up merge
  case .Two:
    // do something else
  default:
    // and so one
}

In this case if you are using the fallthrough keyboard your code is now broken by accident, and depending on what are you trying to do inside the cases you can have a hidden bug that your tests are not seeing right away.

Another advantage is that in this way you can made more cases fallthrough in the same one even if they are not one over each other

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two:
    // do something else that you may want to do for .One and .Two
  default:
    // and so one
}

I must say that this is a side effect that can be used to messed up the code flow in a way that is not intended, but is a new behaviour that gives more power to the switch statement.

The reswitch keyword in addition is not a mere fallthrough on the new case without doing the optional checking attached to it, but is intended to be a new call and all the check are executed.

switch (enum) {
  case .One:
    // do something
    x = 0;
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two where x > 0:
    // do something else that you may want to do for .One and .Two
    element = array
  default:
    // and so one
}
(I’m going by memory and by writing this snippets in the mail app directly, so the code must be incorrect in the syntax and for this I’m sorry).

In this case if enum is .One the only case that is executed is case .One and the code doesn’t fallthrough in the .Two case because we are made the where invalid by changing the x to a value less than 1.

Now I don’t remember who was the first one who mede this proposal, and I don’t know if he is working on a first draft to lay down the things better, but for me this can be a nice improvement and a neat break with the C-switch behaviour that Swift has trying to change from the very first beta disallowing the implicit fallthrough.

I can be completely wrong but I see the `fallthrough`keyword as a “temporary” implementation for ease the transition from Obj-C to Swift and is time to improve it and made the switch statement even more powerful.

- Jacopo
Sent from my iPad

On 06 Dec 2015, at 19:57, Colin Barrett via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

tl;dr The fallthrough keyword, as far as I am aware, isn’t costing us anything; and has at least minimal utility, as I try to demonstrate.

Apologies for jumping into this thread at an awkward point, but I’ve only just now subscribed to this list.

I think the fallthrough keyword is useful in certain circumstances. I’ve also yet to see an example of where it creates a negative impact, either in code, optimization, or what have you. Other than “It’s like something in C, and C is old and busted” I’m unsure of the rationale for removing it. (Feel free to point me in the right direction.)

Consider the Planet enum from the documentation. One of the simplest way to define the number of a planet (i.e. its 1-based index in the ordering of planets wrt. distance from the sun) is using a switch and fall-through:

fallthrough.swift · GitHub

This technique is very extensible — for instance imagine computing the force induced by the gravity of the other planets on a particular planet. All that would need to change is the case statements.

Yes, you could write this by putting the planets into a list and mapping or folding (or looping) over that, but unless the compiler can “unroll” that construct, you’re paying for an allocation simply bc of your choice of control flow. But in fact, you could imagine generalizing this construct into the implementation of fold for the Planet type — low-overhead folds for monomorphic types seems like a pretty compelling an natural use case for fallthrough to me.

Thanks,
-Colin

On Dec 6, 2015, at 4:52 AM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

+1 for this idea, but I will prefer the reswitch keyword instead of overloading continue with a new syntax.

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

Sent from my iPad

On 06 Dec 2015, at 00:23, Steve Canon via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Very much thinking out loud and not really the implications, I wonder if we might just use "continue" instead of "reswitch".

I very much like specifying what case to fall through into, no matter how we spell it.

- Steve

On Dec 5, 2015, at 4:45 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

On Dec 4, 2015, at 11:37 PM, John Calsbeek <john.calsbeek+lists@gmail.com <mailto:john.calsbeek+lists@gmail.com>> wrote:
`fallthrough` is conceptually similar to `goto` in that both allow natural expression of concepts that exist at the instruction level but are otherwise difficult to express with nested control structures. `fallthrough` is perhaps slightly less objectionable because control flow remains local, but it has a similar role.

It is not particularly natural to write `switch` statements with `fallthrough` in the reverse order that can be seen in Duff’s Device and similar constructs (case 7 falls through to 6 which falls through to 5, etc.). It’s just because you know for certain that all the code in case 6 would be duplicated in case 7, so 7 can transfer into 6 without a jump instruction. Communicating that to the compiler without `fallthrough` requires deeply nested `if`s.

Right. One idea that I’ve always had for “fallthrough” is that we might parameterize it in the future; parameterized it would mean “repeat the switch with this new value”, so that unparameterized fallthrough would mean “repeat the switch with a notional value that ends up in the next case”. There’s a very common pattern in switches of deferring to another case that I’ve always found very awkward to write in C, and while sometimes there’s no choice but to extract a helper function, there’s a still-fairly-structural code pattern here that I think we can sensibly support.

On the other hand, there’s an argument that this is an inappropriate extension for “fallthrough” specifically, which is one reason we’ve never pursued it.

Oh, I see that Joe already brought this up, spelled “reswitch”.

John.

John.

One defense comes to mind: there is talk of Swift aiming at systems programming. Is writing a threaded interpreter loop within the potential scope of Swift? That’s a use case that could make use of both `fallthrough` and `goto` (computed goto, really).

switch op {
case LOAD_INDIRECT:
   in0 = memory[in1]
   fallthrough
case LOAD:
   out0 = memory[in0]
//...
}

I am personally interested in the prospect of a language that can scale up to high-level concepts and down to “portable assembler,” but I don’t know if that is the right direction for Swift’s evolution.

Cheers,
John

On Dec 4, 2015, at 2:42 PM, John McCall <rjmccall@apple.com <mailto:rjmccall@apple.com>> wrote:

On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin@sb.org <mailto:kevin@sb.org>> wrote:
It's not actually Duff's Device. Duff's Device relies on the fact that C switch statements don't actually introduce a new scope, and so it overlaps a switch with a do-while loop. This lets it only test the number of bytes once, to jump into the middle of the loop, and then it switches over to a while loop that decrements a counter every 8 instructions. Basically, it's a trick for manual loop unrolling that deals with non-multiple-of-8 counts efficiently.

To be pedantic, C switch statements do introduce a new scope. What Duff’s Device exploits is that switch is allowed to jump into (almost) arbitrary scopes, and cases can appear anywhere recursively inside a switch.

But your point that Swift’s switch requires cases to be at the top level within a switch and thus prevents the use of Duff’s Device is 100% correct.

John.

Steve's code is also an example of manual loop unrolling that deals with non-multiple-of-8 counts, but it has calculate the number of bytes on every iteration instead of once. It's a good example of one of the uses of `fallthrough`, it's just not Duff's Device. It's impossible to use Duff's Device in Swift.

-Kevin Ballard

On Fri, Dec 4, 2015, at 02:16 PM, Greg Titus wrote:

Streza’s source code is an example of Duff’s Device, which is a big place where switch fallthrough is arguably the cleanest way to do things and the reason why I’d personally prefer to keep it as part of the language.

On Dec 4, 2015, at 2:12 PM, Erica Sadun <erica@ericasadun.com <mailto:erica@ericasadun.com>> wrote:

Oh let it die, let it die. Any time I use fallthrough I find myself re-factoring to stop using it.

True fact: On all of gist.github.com <http://gist.github.com/&gt;, there are only 22 gist results for "fallthrough language:swift".
Half of those are people just testing out the feature. Most of the remaining ones are just complex cases:
case .Enum1, .Enum2:
expressed as
case .Enum1: fallthrough
case .Enum2:

And then there's streza: Base32.swift · GitHub I'm pretty sure that ponies were harmed in the production of whatever that last bit is.

On Dec 4, 2015, at 3:05 PM, jalkut@red-sweater.com <mailto:jalkut@red-sweater.com> wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

My understanding is this keyword is only used for the archaic seeming purpose of perpetuating C-style fallthrough from one switch statement to the subsequent one. The documentation hedges the use of this keyword in forbidding terms that make it clear its use is not encouraged. The presence of the keyword, while an improvement over C’s implicit fallthrough, is a mark of inelegance on an otherwise well-designed, opinionated implementation of swtich statements.

The ugliness of fallthrough’s C-style behavior even demands a caveat in the documentation:

"The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior."

To my mind, the caveat explains just what is wrong with fallthrough, both in C or Swift: coded that is clearly labeled with deliberate conditions can nonetheless be reached.

I quipped about this on Twitter, and the most common pushback I got seemed to be from people who either did not know about Swift’s support for comma-separated case statements, or harbored an aesthetic preference for clustering such cases together with fallthrough statements.

In my opinion, unless somebody can think of a strong defense for supporting intentional fallthrough in Swift, removing the keyword would be a move in the direction of minimizing the language’s complexity while also discouraging poor coding style in switch statements.

Thoughts?

Daniel

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

This was previously pitched.

https://lists.swift.org/pipermail/swift-evolution/2015-December/000231.html

Here was the use-case that led to the thread being abandoned:

-- E

···

On Jan 22, 2017, at 11:23 PM, Russ Bishop via swift-evolution <swift-evolution@swift.org> wrote:

On Jan 22, 2017, at 4:53 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Sent from my iPad

On Jan 22, 2017, at 3:15 PM, Chris Lattner <clattner@nondot.org <mailto:clattner@nondot.org>> wrote:

On Jan 20, 2017, at 12:22 PM, Dave Abrahams via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Yeah, maybe there's a more general language feature that could replace 'fallthrough' here. Instead
of labelling cases, we could support a 'reswitch' statement that redispatches the switch to the case
matching the operand:

   switch some_value {
   case .REFINED:
       if !validate(some_value) { return NULL }
       reswitch .BASE

   case .BASE:
       handle_enum_value();
   }

We should just call a spade a spade and spell that "goto" ;-)

Goto has traditionally been used for unstructured control flow, but this form is still fully structured. You cannot produce irreducible loops, jump into scopes, over declarations, etc.

It would be useful to know the technical definition of "structured." The fact is that there's a large category of sensible goto-like jumps that we probably want to allow and I see no advantage to giving them all distinct names. I don't believe users will distinguish them. We already have "break looplabel" and, aside from the label being in the wrong place, it's effectively a goto. It seems to me we should just have goto and either prohibit the troublesome uses or give them reasonable semantics.

I could live with "break" as well as "goto", but it feels a bit like it's pretending to be something it isn't, and there's the source compatibility problem with the label position.

-Dave

I always assumed structured control flow means control only jumps to approved points, not arbitrary statements. Implicitly this is jumping out of a scope to a less-nested scope but never into a more-nested scope.

Swift takes this even further: you are limited to early exit of control flow. That’s a lot more restrictive than arbitrary goto.

Russ

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

Yes, I’m aware that at this time the reswitch can be abused and maybe can be better refined to disallow such cases.

I’m curious, how do you propose to do this?

Checking the case statement is not a problem by itself, but can be a problem if is coupled with a where clause that is not true when you fallthrought.

In your document you give the example:

case .Three where x > 0:

Now I may be wrong but I feel as though most of the uses of where clauses are also ones that reference variables bound in a `case let`. For instance:

case .Four(x) where x > 0:

In that case, fallthrough would required to evaluating the case part anyway, as per my postulated rules below.

In any case, I appreciate you taking the time to discuss your proposal, even if I didn’t end up convinced. Thanks.

-Colin

···

On Dec 6, 2015, at 4:14 PM, Jacopo Andrea Giola <swift-evolution@jacopo.giola.org> wrote:

I’ve written a really bad draft here Draft for changing the fallthorught keyword in Swift language · GitHub
If anyone wants to jump in and elaborate further is welcome. I will try to stay on par with this thread but I’m really bad at writing so every help is welcome.

And if I remember correctly Daniel Jakult was the first one to made this proposal so if he wants to take on and then made the official proposal has every right to do so and I will be very glad if my gist can be a first reference :)

- Jacopo

On 06 Dec 2015, at 21:52, Colin Barrett <colin@springsandstruts.com> wrote:

Apologies, Jacopo, for missing the updated proposal, and thank you for your patience in summarizing it again.

I’ve only glanced through it but my concern here is that it introduces a whole class of new and creative “foot-guns" :) In particular, it allows this construction to loop arbitrarily and creatively, particularly in the case of associated values.

I’m not sure why not checking the case statement is considered a problem for the fallthrough keyword. Assuming it’s impossible to fallthrough to a case that introduces binders (what would they be bound to?), and that this is statically checked (both of which seem reasonable assumptions to me, although if I’m wrong feel free to correct me), isn’t it the entire point of the fallthrough keyword that it skips checking the case statement? I can understand how that might be somewhat confusing (and perhaps it should be documented less prominently) but I’m not sure how it’s a *problem*, exactly...

I think I’m still on the side of keeping fallthrough. What’s the downside of doing nothing? For instance in the case of ++ and -- those features complicate the design of a numerics library.

Thanks,
-Colin

On Dec 6, 2015, at 3:06 PM, Jacopo Andrea Giola <swift-evolution@jacopo.giola.org> wrote:

Hi Colin,

the initial proposal was indeed to remove entirely the `fallthrough` keyword but many people expressed your similar concern and from that point the discussion was steered through an "enhancement" and better refinement of the keyword.

The new idea is to substitute the old keyword with "reswitch" passing the desired new value on which the switch is applied.
So something like this:

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .Two:
    // do something else
  default:
    // and so one
}

This new behaviour, IMO, is better suited for Swift because is more declarative of the developer intent and doesn't carry over unintentional misbehaviour.
Is more declarative because you are forced to state in which case you want to go, and even if the order of the switch’ cases will change in the future, you don't fall in the wrong case by mistake.

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // maybe this change is not made by you but by a messed up merge
  case .Two:
    // do something else
  default:
    // and so one
}

In this case if you are using the fallthrough keyboard your code is now broken by accident, and depending on what are you trying to do inside the cases you can have a hidden bug that your tests are not seeing right away.

Another advantage is that in this way you can made more cases fallthrough in the same one even if they are not one over each other

switch (enum) {
  case .One:
    // do something
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two:
    // do something else that you may want to do for .One and .Two
  default:
    // and so one
}

I must say that this is a side effect that can be used to messed up the code flow in a way that is not intended, but is a new behaviour that gives more power to the switch statement.

The reswitch keyword in addition is not a mere fallthrough on the new case without doing the optional checking attached to it, but is intended to be a new call and all the check are executed.

switch (enum) {
  case .One:
    // do something
    x = 0;
    reswitch .Two
  case .OneAndAHalf
    // so something that you don’t want to do for .One
    reswitch .Two
  case .Two where x > 0:
    // do something else that you may want to do for .One and .Two
    element = array
  default:
    // and so one
}
(I’m going by memory and by writing this snippets in the mail app directly, so the code must be incorrect in the syntax and for this I’m sorry).

In this case if enum is .One the only case that is executed is case .One and the code doesn’t fallthrough in the .Two case because we are made the where invalid by changing the x to a value less than 1.

Now I don’t remember who was the first one who mede this proposal, and I don’t know if he is working on a first draft to lay down the things better, but for me this can be a nice improvement and a neat break with the C-switch behaviour that Swift has trying to change from the very first beta disallowing the implicit fallthrough.

I can be completely wrong but I see the `fallthrough`keyword as a “temporary” implementation for ease the transition from Obj-C to Swift and is time to improve it and made the switch statement even more powerful.

- Jacopo
Sent from my iPad

On 06 Dec 2015, at 19:57, Colin Barrett via swift-evolution <swift-evolution@swift.org> wrote:

tl;dr The fallthrough keyword, as far as I am aware, isn’t costing us anything; and has at least minimal utility, as I try to demonstrate.

Apologies for jumping into this thread at an awkward point, but I’ve only just now subscribed to this list.

I think the fallthrough keyword is useful in certain circumstances. I’ve also yet to see an example of where it creates a negative impact, either in code, optimization, or what have you. Other than “It’s like something in C, and C is old and busted” I’m unsure of the rationale for removing it. (Feel free to point me in the right direction.)

Consider the Planet enum from the documentation. One of the simplest way to define the number of a planet (i.e. its 1-based index in the ordering of planets wrt. distance from the sun) is using a switch and fall-through:

fallthrough.swift · GitHub

This technique is very extensible — for instance imagine computing the force induced by the gravity of the other planets on a particular planet. All that would need to change is the case statements.

Yes, you could write this by putting the planets into a list and mapping or folding (or looping) over that, but unless the compiler can “unroll” that construct, you’re paying for an allocation simply bc of your choice of control flow. But in fact, you could imagine generalizing this construct into the implementation of fold for the Planet type — low-overhead folds for monomorphic types seems like a pretty compelling an natural use case for fallthrough to me.

Thanks,
-Colin

On Dec 6, 2015, at 4:52 AM, Jacopo Andrea Giola via swift-evolution <swift-evolution@swift.org> wrote:

+1 for this idea, but I will prefer the reswitch keyword instead of overloading continue with a new syntax.

If this proposal is accepted, it must be coupled with a compiler check that the reswitch statements don't introduce an infinite "switch" loop.

Sent from my iPad

On 06 Dec 2015, at 00:23, Steve Canon via swift-evolution <swift-evolution@swift.org> wrote:

Very much thinking out loud and not really the implications, I wonder if we might just use "continue" instead of "reswitch".

I very much like specifying what case to fall through into, no matter how we spell it.

- Steve

On Dec 5, 2015, at 4:45 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <swift-evolution@swift.org> wrote:

On Dec 4, 2015, at 11:37 PM, John Calsbeek <john.calsbeek+lists@gmail.com> wrote:
`fallthrough` is conceptually similar to `goto` in that both allow natural expression of concepts that exist at the instruction level but are otherwise difficult to express with nested control structures. `fallthrough` is perhaps slightly less objectionable because control flow remains local, but it has a similar role.

It is not particularly natural to write `switch` statements with `fallthrough` in the reverse order that can be seen in Duff’s Device and similar constructs (case 7 falls through to 6 which falls through to 5, etc.). It’s just because you know for certain that all the code in case 6 would be duplicated in case 7, so 7 can transfer into 6 without a jump instruction. Communicating that to the compiler without `fallthrough` requires deeply nested `if`s.

Right. One idea that I’ve always had for “fallthrough” is that we might parameterize it in the future; parameterized it would mean “repeat the switch with this new value”, so that unparameterized fallthrough would mean “repeat the switch with a notional value that ends up in the next case”. There’s a very common pattern in switches of deferring to another case that I’ve always found very awkward to write in C, and while sometimes there’s no choice but to extract a helper function, there’s a still-fairly-structural code pattern here that I think we can sensibly support.

On the other hand, there’s an argument that this is an inappropriate extension for “fallthrough” specifically, which is one reason we’ve never pursued it.

Oh, I see that Joe already brought this up, spelled “reswitch”.

John.

John.

One defense comes to mind: there is talk of Swift aiming at systems programming. Is writing a threaded interpreter loop within the potential scope of Swift? That’s a use case that could make use of both `fallthrough` and `goto` (computed goto, really).

switch op {
case LOAD_INDIRECT:
   in0 = memory[in1]
   fallthrough
case LOAD:
   out0 = memory[in0]
//...
}

I am personally interested in the prospect of a language that can scale up to high-level concepts and down to “portable assembler,” but I don’t know if that is the right direction for Swift’s evolution.

Cheers,
John

On Dec 4, 2015, at 2:42 PM, John McCall <rjmccall@apple.com> wrote:

On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin@sb.org> wrote:
It's not actually Duff's Device. Duff's Device relies on the fact that C switch statements don't actually introduce a new scope, and so it overlaps a switch with a do-while loop. This lets it only test the number of bytes once, to jump into the middle of the loop, and then it switches over to a while loop that decrements a counter every 8 instructions. Basically, it's a trick for manual loop unrolling that deals with non-multiple-of-8 counts efficiently.

To be pedantic, C switch statements do introduce a new scope. What Duff’s Device exploits is that switch is allowed to jump into (almost) arbitrary scopes, and cases can appear anywhere recursively inside a switch.

But your point that Swift’s switch requires cases to be at the top level within a switch and thus prevents the use of Duff’s Device is 100% correct.

John.

Steve's code is also an example of manual loop unrolling that deals with non-multiple-of-8 counts, but it has calculate the number of bytes on every iteration instead of once. It's a good example of one of the uses of `fallthrough`, it's just not Duff's Device. It's impossible to use Duff's Device in Swift.

-Kevin Ballard

On Fri, Dec 4, 2015, at 02:16 PM, Greg Titus wrote:

Streza’s source code is an example of Duff’s Device, which is a big place where switch fallthrough is arguably the cleanest way to do things and the reason why I’d personally prefer to keep it as part of the language.

On Dec 4, 2015, at 2:12 PM, Erica Sadun <erica@ericasadun.com> wrote:

Oh let it die, let it die. Any time I use fallthrough I find myself re-factoring to stop using it.

True fact: On all of gist.github.com, there are only 22 gist results for "fallthrough language:swift".
Half of those are people just testing out the feature. Most of the remaining ones are just complex cases:
case .Enum1, .Enum2:
expressed as
case .Enum1: fallthrough
case .Enum2:

And then there's streza: Base32.swift · GitHub I'm pretty sure that ponies were harmed in the production of whatever that last bit is.

On Dec 4, 2015, at 3:05 PM, jalkut@red-sweater.com wrote:

In the spirit of some other proposals that remove C or C++ style artifacts, what do folks think about the possibility of removing the "fallthrough" keyword from the language?

My understanding is this keyword is only used for the archaic seeming purpose of perpetuating C-style fallthrough from one switch statement to the subsequent one. The documentation hedges the use of this keyword in forbidding terms that make it clear its use is not encouraged. The presence of the keyword, while an improvement over C’s implicit fallthrough, is a mark of inelegance on an otherwise well-designed, opinionated implementation of swtich statements.

The ugliness of fallthrough’s C-style behavior even demands a caveat in the documentation:

"The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior."

To my mind, the caveat explains just what is wrong with fallthrough, both in C or Swift: coded that is clearly labeled with deliberate conditions can nonetheless be reached.

I quipped about this on Twitter, and the most common pushback I got seemed to be from people who either did not know about Swift’s support for comma-separated case statements, or harbored an aesthetic preference for clustering such cases together with fallthrough statements.

In my opinion, unless somebody can think of a strong defense for supporting intentional fallthrough in Swift, removing the keyword would be a move in the direction of minimizing the language’s complexity while also discouraging poor coding style in switch statements.

Thoughts?

Daniel

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution