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

Alex Lew alexl.mail+swift at gmail.com
Sun Dec 6 15:36:01 CST 2015


One question: what is the result of this code?

let x = .One

switch x {
case .One:
   reswitch(.Two)
case .Two:
   return x
}

.One or .Two? In other words, is x rebound inside the switch when we
reswitch?

On Sun, Dec 6, 2015 at 4:28 PM, Alex Lew <alexl.mail+swift at gmail.com> wrote:

> It seems reswitch *should* be useable even in cases that aren't a simple
> "goto". Or am I missing something?
>
> For instance, rewriting the example from earlier:
>
> switch op {
> case let .LOAD_INDIRECT(out, in):
>     reswitch(.LOAD(out, memory[in]))
> case let .LOAD(out, in):
>     setReg(out, in)
> // ...
> }
>
> or, a switch that calculates whether some number n is in a Lisp-style list
> of numbers
>
> switch lst {
> case .Cons(let m, _) where m == n:
>      return true
> case .Cons(_, let rest):
>     reswitch(rest)
> case .Empty:
>      return false
> }
>
> I like reswitch: in some cases, the compiler could optimize to a
> fallthrough, and in others, you could actually re-switch. But maybe I'm
> missing something.
>
> On Sun, Dec 6, 2015 at 4:14 PM, Jacopo Andrea Giola via swift-evolution <
> swift-evolution at swift.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.
>>
>> 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
>> 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
>>
>>
>>
>> Untracked with Trackbuster <https://trackbuster.com/?sig>
>>
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151206/aa1365c7/attachment-0001.html>


More information about the swift-evolution mailing list