Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a swift switch be exhaustive for type Double without a default case?

Can a swift switch be exhaustive for type Double without a default case?

This switch (without a default case) gives the error: switch must be exhaustive:

    var minY = 1.0

    switch minY {
    case -(Double.infinity)..<0.9:
        yAxisMinimum = 0.0
    case (0.9..<0.99):
        yAxisMinimum = 0.9
    case (0.99..<0.999):
        yAxisMinimum = 0.99
    case (0.999..<0.9999):
        yAxisMinimum = 0.999
    case (0.9999...Double.infinity):
        yAxisMinimum = 0.9999
    }

But this switch, with the (useless) default case, works:

    var minY = 1.0

    switch minY {
    case -(Double.infinity)..<0.9:
        yAxisMinimum = 0.0
    case (0.9..<0.99):
        yAxisMinimum = 0.9
    case (0.99..<0.999):
        yAxisMinimum = 0.99
    case (0.999..<0.9999):
        yAxisMinimum = 0.999
    case (0.9999...Double.infinity):
        yAxisMinimum = 0.9999
    default:
        yAxisMinimum = 0.0
    }

I try to avoid default cases with my switches, but don't know if that's possible with a Double.

like image 839
Darrell Root Avatar asked Feb 10 '19 23:02

Darrell Root


People also ask

Can you use a switch case without a default?

A switch statement can have an optional default case, which must appear at the end of the switch. The default case can be used for performing a task when none of the cases is true. No break is needed in the default case.

What does switch must be exhaustive?

The section about control flow of the language guide says: Every switch statement must be exhaustive. That is, every possible value of the type being considered must be matched by one of the switch cases.

Should default be last in switch case?

A 'switch' statement should have 'default' as the last label. Adding a 'default' label at the end of every 'switch' statement makes the code clearer and guarantees that any possible case where none of the labels matches the value of the control variable will be handled.

How do you skip a switch case in Swift?

You do this by writing the break statement as the entire body of the case you want to ignore."


1 Answers

No because only enum types can be exhaustively checked.

But in this case, the problem is even deeper. Even if Integers could be exhaustively checked, you still couldn't exhaustively check Double without a where clause. One of the options is .nan ("not a number"), which you're not considering. So you might think to just add that case:

case .nan:
    yAxisMinimum = .nan

Not only won't this make it exhaustive, it won't even work the way you'd expect.

var minY = Double.nan

switch minY {
case -(Double.infinity)..<0.9:
    yAxisMinimum = 0.0
// ...
case .nan:
    yAxisMinimum = .nan
default:
    yAxisMinimum = 0
}

yAxisMinimum // 0

Why? Because of this:

var minY = Double.nan
minY == .nan   // false

NaN is unequal to everything, including NaN. So there's no way to include it directly in a switch statement. You have to use a where clause:

case _ where minY.isNaN:
    yAxisMinimum = .nan

And that's definitely beyond the compiler's ability to validate.

like image 140
Rob Napier Avatar answered Sep 28 '22 03:09

Rob Napier