4

Scalaの「一致」セマンティクスまたはコンパイラロジックについて、基本的な誤解が必要です。このコード:

val stageStart:Int = 0
val stageShutDown:Int = Int.MaxValue
val stageErrorReport:Int = Int.MinValue

def stageString(stage:Int):String = stage match {
  case stageStart       => "Start"
  case stageShutDown    => "End"
  case stageErrorReport => "Error"
  case _                => "Step " + String.valueOf(stage)
}

最後の3つの「case」ステートメントで「到達不能コード」エラーが発生しますか?名前の代わりに実際の値(0、Int.MaxValue、Int.MinValue)に置き換えると、コンパイルされますが、(通常の理由で)名前で参照する必要のある値をハードコーディングしました。'val'は決して変更できないので、最初のバージョンも機能するべきではありませんか?

4

2 に答える 2

9

There is a subtle yet important feature: If the identifier in case rules start with a lower-case letter, they're always treated as variables. So the first case matches always (storing stage into variable stageStart) and the rest 3 are unreachable. You need to define the constants with upper case letters as

val StageStart:Int = 0
val StageShutDown:Int = Int.MaxValue
val StageErrorReport:Int = Int.MinValue

def stageString(stage:Int):String = stage match {
  case StageStart       => "Start"
  case StageShutDown    => "End"
  case StageErrorReport => "Error"
  case _                => "Step " + String.valueOf(stage)
}

Then they won't be treated as variables but as constants to pattern-match on.

See also this answer for Naming convention for Scala constants?

于 2012-08-29T18:32:07.757 に答える
8

The issue is that when you use a variable that starts with a lowercase character, the pattern matcher thinks that you are trying to assign to that variable. So you get this behavior:

val stageStart = 0
val stage = 5
def stageString(stage: Int) = stage match {
  case stageStart => println(startStage)  // prints "5"
}

Of course, a pattern that is simply an assignable variable will match anything, so any subsequent case will be unreachable.

To solve this, you need to use a "stable identifier". This can be done by putting the lowercased variable in backticks:

val stageStart = 0
def stageString(stage: Int) = stage match {
  case `stageStart` => "Start"
}

or renaming the variable so that it starts with an uppercase character:

val StageStart = 0
def stageString(stage: Int) = stage match {
  case StageStart => "Start"
}

Also: String.valueOf(stage) should be rewritten as stage.toString.

于 2012-08-29T18:32:18.163 に答える