[swift-evolution] [Pitch] Can we make `default` on switches optional?

Rien Rien at Balancingrock.nl
Mon Oct 3 06:54:28 CDT 2016


> On 03 Oct 2016, at 13:16, Ross O'Brien <narrativium+swift at gmail.com> wrote:
> 
> There has been a little discussion on this before, and I think there's a need for something along these lines - I've written code where I've used 'guard' to ensure that an Int was within a certain range, and then performed a switch on the Int, requiring an ugly-looking 'default: fatalError()' at the end to dismiss the warning.
> 
> But exhaustive switches are also useful.
> 
> There was an elegant suggestion that we apply '?' and '!' to the switch keyword. Basically:
> - 'switch <expression>' is exhaustive across values and enum states and the compiler will warn you if you omit an enum state or default case.
> - 'switch? <expression>' is not exhaustive but the compiler should still check the flow (to ensure all paths return values, that kind of thing).

Swift: The questionable language… lol

> - 'switch! <expression>' is not exhaustive but it assumes one of the cases will match, and crashes otherwise.
> 
> Basically, switch wouldn't change, but appending the '?' is equivalent to typing 'default: break' as your final case, and appending '!' is equivalent to typing 'default: fatalError()' as your final case. The meanings are roughly analogous to their meanings for Optionals, so hopefully there wouldn't be much confusion.
> 

Though I am not 100% on the “feel” of this, it would work imo.

Rien.

> 
> On Mon, Oct 3, 2016 at 11:55 AM, Adrian Zubarev via swift-evolution <swift-evolution at swift.org> wrote:
> This is clearly not a huge issue to solve, but a pitch is a pitch.
> 
> From Swift book we know this:
> 
> Switch Statements Must Be Exhaustive
> 
> In Swift, every possible value of the control expression’s type must match the value of at least one pattern of a case. When this simply isn’t feasible (for instance, when the control expression’s type is Int), you can include a default case to satisfy the requirement.
> 
> Even for enum values an optional default would mean that you don’t care about the other cases in your current switch, which basically again would be another useless nop.
> 
> enum A {
>     case a, b, c
> }
> 
> var value = A.a
> 
> switch value {
>      
> case .a:
>     value = A.b
>      
> default:
>     () // I don't care
> }
> 
> // Do something else  
> 
> switch value {
>      
> case .b:
>     value = A.c
>      
> default:
>     () // I don't care
> }
> 
> Sure the error message is there to notify you that you might forget to handle some case, but how we handle that specific case is still up to us.
> 
> I’d really like to know what could be dangerous here when default would be optional.
> 
> I can’t tell if this would have some impact on the ABI or not. I’d say it’s additive because it doesn’t break any existing code but removes an existing restriction.
> 
> The next thought might be an overkill (or maybe not):
> 
> How about making default optional everywhere + introducing a new attribute that allows the optional default on that particular enum, but by default every current existing enum should be handled exhaustively.
> 
> Bikeshedding:
> 
> enum A {
>     case a, b, c
> }
> 
> var value = A.a
> 
> switch value {
>      
> case .a:
>     value = A.b
>      
> } // Error: switch must be exhaustive, consider adding a default clause
> 
> // VS:
> 
> @discardableCase enum B {
>     case d, e, f
> }
> 
> let anotherValue = B.d
> 
> switch anotherValue {
>      
> case .d:
>     // Do something
>      
> case .e:
>     // Do something else
>          
> } // Just fine; We don't care here about `.f`
> 
> 
> 
> 
> -- 
> Adrian Zubarev
> Sent with Airmail
> 
> Am 3. Oktober 2016 um 12:28:58, Rien (rien at balancingrock.nl) schrieb:
> 
>> On non-enum values, yes I could support this. However I do not see this as a big enough issue. 
>> On enum values? no way…. 
>> 
>> Btw this would get rid of: 
>> 
>> let bytesSend = send(…) // returns an Int 
>> 
>> switch bytesSend { 
>> case Int.min ... -1: {…} 
>> case 0: {…} 
>> case 1 ... Int.max: {…} 
>> default: break // <<<<<< Imposible 
>> } 
>> 
>> 
>> 
>> 
>> > On 03 Oct 2016, at 12:14, Adrian Zubarev via swift-evolution <swift-evolution at swift.org> wrote: 
>> > 
>> > I know that there is this note in Commonly Rejected Changes: 
>> > 
>> > Remove support for default: in switch and just use case _:: default is widely used, case _ is too magical, and default is widely precedented in many C family languages. 
>> > I really like to use the switch instead of if case for pattern matching, just because it’s neat block design. I do not want to remove default from switches because it’s a must have and powerful feature. 
>> > 
>> > I’d like to know why switches must be exhaustive. 
>> > 
>> > switch someValue { 
>> > 
>> > case …: 
>> > // Do something 
>> > 
>> > case …: 
>> > // Do something else 
>> > 
>> > default: 
>> > () // useless nop; do nothing when no pattern matched 
>> > } 
>> > 
>> > // VS: 
>> > 
>> > if case … { 
>> > 
>> > } else if case … { 
>> > 
>> > } else if case … { 
>> > 
>> > } // No need for `else` 
>> > 
>> > Can’t we make default optional, or at least on non-enum values? 
>> > 
>> > 
>> > 
>> > 
>> > -- 
>> > Adrian Zubarev 
>> > Sent with Airmail 
>> > 
>> > _______________________________________________ 
>> > 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
> 
> 



More information about the swift-evolution mailing list