[swift-evolution] Proposal: Remove the "fallthrough" keyword

Dan Appel dan.appel00 at gmail.com
Sun Dec 6 15:26:02 CST 2015


For better or worse, I would like to note that `reswitch` is essentially a
safer `goto`, so keep in mind all the bad things that can be done with it.

On Sun, Dec 6, 2015 at 1:23 PM Colin Barrett via swift-evolution <
swift-evolution at swift.org> wrote:

>
> > On Dec 6, 2015, at 4:14 PM, Jacopo Andrea Giola <
> swift-evolution at jacopo.giola.org> wrote:
> >
> > 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
>
> > I’ve written a really bad draft here
> https://gist.github.com/JGiola/f735212789bf2f697847
> > 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 at 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 at 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[x]
> >>>     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 at 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:
> >>>>
> >>>> https://gist.github.com/cbarrett/23b24a9fe76efdf006df
> >>>>
> >>>> 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 at 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 at 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 at swift.org> wrote:
> >>>>>>
> >>>>>>>> On Dec 5, 2015, at 1:31 PM, John McCall via swift-evolution <
> swift-evolution at swift.org> wrote:
> >>>>>>>>> On Dec 4, 2015, at 11:37 PM, John Calsbeek <
> john.calsbeek+lists at 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 at apple.com>
> wrote:
> >>>>>>>>>>
> >>>>>>>>>>> On Dec 4, 2015, at 2:33 PM, Kevin Ballard <kevin at 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 at 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:
> https://gist.github.com/stevestreza/2557dc5ec9e7c694d7ea   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 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?
> >>>>>>>>>>>>>>
> >>>>>>>>>>>>>> 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 at swift.org
> >>>>>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>>>>>>>>>>
> >>>>>>>>>>>>>
> >>>>>>>>>>>>> _______________________________________________
> >>>>>>>>>>>>> swift-evolution mailing list
> >>>>>>>>>>>>> swift-evolution at swift.org
> >>>>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>>>>>>>>>
> >>>>>>>>>>>>
> >>>>>>>>>>>> _______________________________________________
> >>>>>>>>>>>> swift-evolution mailing list
> >>>>>>>>>>>> swift-evolution at swift.org
> >>>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>>>>>>>>
> >>>>>>>>>>>
> >>>>>>>>>>> _______________________________________________
> >>>>>>>>>>> swift-evolution mailing list
> >>>>>>>>>>> swift-evolution at swift.org
> >>>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>>>>>>>
> >>>>>>>>>>  _______________________________________________
> >>>>>>>>>> swift-evolution mailing list
> >>>>>>>>>> swift-evolution at swift.org
> >>>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>>>>>>
> >>>>>>>>>
> >>>>>>>>> _______________________________________________
> >>>>>>>>> swift-evolution mailing list
> >>>>>>>>> swift-evolution at swift.org
> >>>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>>>>>
> >>>>>>>>
> >>>>>>>> _______________________________________________
> >>>>>>>> swift-evolution mailing list
> >>>>>>>> swift-evolution at swift.org
> >>>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>>>>
> >>>>>>>
> >>>>>>> _______________________________________________
> >>>>>>> swift-evolution mailing list
> >>>>>>> swift-evolution at swift.org
> >>>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>>>
> >>>>>> _______________________________________________
> >>>>>> swift-evolution mailing list
> >>>>>> swift-evolution at swift.org
> >>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>>
> >>>>> _______________________________________________
> >>>>> swift-evolution mailing list
> >>>>> swift-evolution at swift.org
> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>>>
> >>>>
> >>>> _______________________________________________
> >>>> swift-evolution mailing list
> >>>> swift-evolution at swift.org
> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution
> >>
> >
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-- 
Dan Appel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151206/c4c125eb/attachment.html>


More information about the swift-evolution mailing list