16

Enumerated values seem to fail in match/case expressions. This is what happens in a worksheet.

  object EnumType extends Enumeration {
    type EnumType = Value
    val a, b = Value
  }

  import EnumType._
  val x: EnumType = b                //> x : ... .EnumType.EnumType = b

  x match {
    case a => "a"
    case b => "b"
  }                                  //> res0: String = a

  if (x == a) "a" else "b"           //> res1: String = b

What's going on? Thanks.

RussAbbott
  • 2,660
  • 4
  • 24
  • 37

3 Answers3

25

Like @Kevin Wright and @Lee just said, a and b work as variable patterns, not as EnumType values.

Another option to fix your code is making it explicit you are referencing values from the EnumType singleton:

scala> x match { case EnumType.a => "a" case EnumType.b => "b" }
res2: String = b
rsenna
  • 11,775
  • 1
  • 54
  • 60
13

The a and b in your match block aren't the same as the enumerated values a and b, the pattern matcher will simply match x in the first case and bind it to a new value a (the second case will be ignored)

To avoid this, you have two choices:

1) wrap the values in backticks:

x match {
  case `a` => "a"
  case `b` => "b"
}     

2) Make the enumerated values uppercase:

object EnumType extends Enumeration {
  type EnumType = Value
  val A, B = Value
}

import EnumType._
val x: EnumType = B

x match {
  case A => "a"
  case B => "b"
}   

Given that these values are (to all intents an purposes) constants, using uppercase is the more common/idiomatic solution.

Note that only the initial letter needs to be uppercase, not the name of the entire literal.

Kevin Wright
  • 49,540
  • 9
  • 105
  • 155
  • Thanks. I wasn't aware of either the Upper case or backtick convention for case statements. (PS. I checked the checkmark indicating that the question was answered, but when I checked the checkmark on the the answer above, this answer became unchecked.) – RussAbbott Jan 28 '14 at 19:05
  • 2
    Feel free to accept whatever rocks your boat the most :) Incidentally, you can always change an accepted answer if something else comes along that you think is a better fit for the question. – Kevin Wright Jan 28 '14 at 19:25
  • 1
    I'd go also with making them uppercase anyway, respects the naming convention and also won't be treated as a value pattern in pattern matching – Nader Ghanbari Oct 17 '16 at 23:59
3

a in your case statement is an unbound variable which matches anything. You need to explicitly check the value is equal to a:

x match {
    case v if v == a => "a"
    case _ => "b"
}
Lee
  • 142,018
  • 20
  • 234
  • 287