0

I'm using swift and I have encountered an error when using switch statement and greater than > to compare a number.

Xcode display the following message: expression pattern of type "Bool" cannot match values of type "Int"

I know that by replacing case self > 0: return .positive with case let x where x > 0: return .positive, everything works just fine.

But I don't really understand why case self > 0: return .positive is not allowed? What is the reason behind it?

extension Int {
    enum Kind {
        case negative, zero, positive
    }
    var kind: Kind {
        switch self {
        case 0:
            return .zero
//Error: expression pattern of type "Bool" cannot match values of type "Int"
//        case self > 0:
//            return .positive
        case let x where x > 0: //this works
            return .positive
        default:
            return .negative
        }
    }

}
halfer
  • 19,824
  • 17
  • 99
  • 186
Thor
  • 9,638
  • 15
  • 62
  • 137
  • 1
    error message is telling you everything. expression pattern of type "Bool" cannot match values of type "Int" – Sahil Oct 19 '16 at 06:50
  • 1
    Compare http://stackoverflow.com/questions/33975542/swift-2-expression-pattern-of-type-bool-cannot-match-values-of-type-int for a similar question. – Martin R Oct 19 '16 at 06:54
  • 2
    In Swift 3 `case 1...Int.max:` would also work. – Martin R Oct 19 '16 at 06:59
  • @MartinR thanks for all the helpful comment! i'm very honoured to be helped out by an swift expert :) – Thor Oct 19 '16 at 07:02
  • The "positive" case can also be checked with `case _ where self > 0:` – as mentioned in a comment http://stackoverflow.com/questions/36476599/swift-switch-statement-considered-all-cases-of-int-but-compiler-still-display-e/36477188#comment60570202_36476599 to one of your older questions. – Martin R Oct 19 '16 at 07:33
  • @MartinR Ah, that Q&A. W.r.t. the discussion in the comments to your answer there: it seems that even after the introduction of `ClosedRange`, the `switch` blocks are still unable to deduce that e.g. cases `Int.min...0` and `1...Int.max` are exhaustive (demaning a default case). – dfrib Oct 19 '16 at 07:39
  • @dfri: Yes, I noticed that and have updated that part accordingly. Thanks for the feedback! – Martin R Oct 19 '16 at 07:42

3 Answers3

3

This is a simple rule about switch statements.

In each case of a switch statement, the expression that follows immediately after case is evaluated and compared to the thing that you are switching on.

So in your code, self > 0 is evaluated and compared with self. Assuming self is 10,

self > 0 == self
true == 10 // WTF?

The second case let x where x > 0 is different, let x is not an expression. It basically saying:

In this case, I want a variable called x to be assigned the value of self. But please only do this if x > 0 after doing the assignment. If !(x > 0), go to another case.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • thank you so much! that makes perfect sense! had a difficult time getting my head around this. Thanks again! – Thor Oct 19 '16 at 06:59
1

Error message is telling you everything. expression pattern of type "Bool" cannot match values of type "Int".

case self > 0: // it will return Bool value but It needs to be a pattern against which the value can be matched
Sahil
  • 9,096
  • 3
  • 25
  • 29
  • 3
    No, a case expression need not be a constant expression as you can see in `case let x where x > 0:`. It needs to be a *pattern* against which the value can be matched. – Martin R Oct 19 '16 at 06:56
  • I agree. It needs to be a pattern against which the value can be matched. – Sahil Oct 19 '16 at 06:59
1

Since switch statements performs pattern matching, you needn't necessarily bind the value of self and test for inequality/equality for some case, but could modify your positive case for direct pattern matching of self to the range 1...Int.max. E.g.

extension Int {
    enum Kind {
        case negative, zero, positive
    }
    var kind: Kind {
        switch self {
        case 0:
            return .zero
        case 1...Int.max:
            return .positive
        default:
            return .negative
        }
    }
}
dfrib
  • 70,367
  • 12
  • 127
  • 192
  • 1
    Why not `case: 1...Int.max:` ? (http://stackoverflow.com/questions/40124019/why-case-self-0-return-positive-is-not-allowed-in-switch-statement#comment67518701_40124019) – Martin R Oct 19 '16 at 07:26
  • @MartinR Of course, thanks (for some reason I was stuck wanting to represent the open-closed range `(0, Int.max]`, satisfied with `[0, Int.max]` with guaranteed `0` exclusion, without considering the fact that we're working with integers). Missed that you'd already mentioned this in a comment to the Q! – dfrib Oct 19 '16 at 07:29