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

Ross O'Brien narrativium+swift at gmail.com
Mon Oct 3 06:16:52 CDT 2016


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).
- '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.


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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161003/006340b8/attachment.html>


More information about the swift-evolution mailing list