[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