Scala枚举类型在match/case中失败

16

枚举值在匹配/情况表达式中似乎无法使用。这是在工作表中发生的情况。

  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

发生了什么事?谢谢。


你应该已经收到了一个警告,第二个 case 永远不会匹配,对吧? - Randall Schulz
1
同样的代码在.scala文件中会产生一个警告,但在工作表中不会。 - RussAbbott
3个回答

25

就像@Kevin Wright和@Lee刚才说的那样,ab作为变量模式工作,而不是EnumType值。

修复代码的另一个选项是明确引用EnumType单例中的值:

scala> x match { case EnumType.a => "a" case EnumType.b => "b" }
res2: String = b

13

你的match块中的ab与枚举值ab不同,模式匹配器将在第一种情况下简单匹配x并将其绑定到一个新值a(第二种情况将被忽略)。

为避免这种情况,你有两个选择:

1) 将值用反引号括起来:

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

2) 将枚举值大写:

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"
}   

考虑到这些值本质上是常量,使用大写字母是更普遍/惯用的解决方案。

请注意,只需要将首字母大写,而不是整个文字的名称。


谢谢。我之前不知道在case语句中可以使用大写或反引号的约定。(顺便说一下,我已经勾选了问题已被回答的复选框,但当我勾选上面答案的复选框时,这个答案变成了未勾选状态。) - RussAbbott
2
请随意选择最适合你的答案 :) 顺便说一句,如果有其他更合适的答案出现,你可以随时更改已接受的答案。 - Kevin Wright
1
我也会选择将它们转换为大写,这样尊重命名约定,并且在模式匹配中也不会被视为值模式。 - Nader Ghanbari

3

case语句中的a是一个未绑定的变量,可以匹配任何东西。您需要明确检查该值是否等于a

x match {
    case v if v == a => "a"
    case _ => "b"
}

1
这基本上与 if 表达式的版本相同。 - RussAbbott
请查看另外两个回答,它们实际上解释了为什么会发生这种情况。 - Nader Ghanbari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接