switch over enum of integers

I'm probably missing something obvious here, but I'm wondering why using a switch with enum cases doesn't work:


protocol IntegerComparableEnum {
  var rawValue: Int { get }
}

func ~= (pattern: IntegerComparableEnum, value: Int) -> Bool {
  return pattern.rawValue == value
}

enum Foobar: Int, IntegerComparableEnum {
  case Zero, One, Two
}

// "enum case 'Zero' is not a member of type 'Int'
switch someValue {
case Foobar.Zero: print("0")
case Foobar.First: print("1")
case Foobar.Second: print("2")
}


when using the the pattern matching operator manually it works as expected:


let someValue = 1
let result = Foobar.One ~= someValue
print("result is \(result)")  // prints "result is true"


Any idea what I'm doing wrong in the first case?


Thanks,

Axel

This related version works:


protocol IntegerComparableEnum {
  var rawValue: Int { get }
}

func ~= (pattern: IntegerComparableEnum, value: Int) -> Bool {
  return pattern.rawValue == value
}


struct Foobar: IntegerComparableEnum {
  var rawValue: Int

  init (rawValue: Int) {
  self.rawValue = rawValue
  }

  static let Zero = Foobar (rawValue: 0)
  static let First = Foobar (rawValue: 1)
  static let Second = Foobar (rawValue: 2)
}

let someValue = 1

switch someValue { // prints "1"
  case Foobar.Zero: print("0")
  case Foobar.First: print("1")
  case Foobar.Second: print("2")
  default: print ("none")
}


My guess is that yours won't compile because "enum cases" as switch cases is a syntactic pattern, separate from other syntactic patterns such as "value binding", "typecasting", etc. In effect, your code is ambiguous, because the compiler doesn't know whether you mean to match on enum cases or ~='ed pattern matches (and apparently it assumes the former).


So, it might be a compiler bug, or it might correctly be an error but one with an unhelpful message. About all you can do is submit a bug report and look for a workaround in the short term.

your enum states : case Zero, One, Two


your switch says Foobar.Zero, Foobar.First:, Foobar.Second and not Foobar.One, Foobar.Two

Is that on purpose ?

Oh, no, that's just an oversight. The example was cobbled together from an actual project, so I missed renaming the identifers in the switch statement. Thanks for pointing it out. Unfortunately it doesn't change my question though

Yeah, that would be a workaround. Another workaround would be to directly use the enum's rawValue in the switch statement, but the whole point of the custom pattern matching should be to be able to get around doing this (at least the way I understand it).

I wasn't so much suggesting a workaround as demonstrating (at least to my own satisfaction) that your pattern matching function was working. I just tried this test (in a playground):


func ~= (pattern: Int, value: Int) -> Bool {
  return pattern == value + 1
}

let someValue = 1

switch someValue {
  case 0: print("0")
  case 1: print("1")
  case 2: print("2")
  default: print ("none")
}


This does work correctly (prints "2", not "1", because I forced the pattern matching function to give the "wrong" answer). It looks like the enum case just isn't being handled properly by the compiler. (I also tried using the enum directly in the pattern matching function, and that doesn't work either.)


P.S. As a side issue, it's obviously a really, really bad idea to have a ~= function that takes (Int, Int) parameters. Or, this would be a useful way to use Swift to prove that 1 + 1 = 3. 🙂

Thinking about this some more: the whole "invisible" pattern matching thing seems like a really bad idea, period. Defining the ~= function with inappropriate parameters could easily invalidate an entire project's logic. Submitted this complaint (along with the fact that your original use case doesn't work) as bug #24915658.

switch over enum of integers
 
 
Q