web-dev-qa-db-ja.com

Scala=のパターンマッチングが変数で機能しないのはなぜですか?

次の機能を実行します。

def fMatch(s: String) = {
    s match {
        case "a" => println("It was a")
        case _ => println("It was something else")
    }
}

このパターンはうまくマッチします:

scala> fMatch("a")
It was a

scala> fMatch("b")
It was something else

私ができることは、次のことです。

def mMatch(s: String) = {
    val target: String = "a"
    s match {
        case target => println("It was" + target)
        case _ => println("It was something else")
        }
}

これにより、次のエラーが発生します。

fMatch: (s: String)Unit
<console>:12: error: unreachable code
               case _ => println("It was something else")

これは、ターゲットが実際には入力が何であれ割り当てたい名前だと考えているためだと思います。 2つの質問:

  1. なぜこの動作ですか?適切なタイプを持つスコープ内の既存の変数を探して最初にそれらを使用し、見つからない場合はターゲットをパターンマッチする名前として扱うことはできませんか?

  2. これに対する回避策はありますか?変数とパターンマッチする方法はありますか?最終的には大きなifステートメントを使用できますが、マッチケースはよりエレガントです。

106
Henry Henrinson

探しているのは安定した識別子です。 Scalaでは、これらは大文字で始めるか、バッククォートで囲む必要があります。

これらは両方とも問題の解決策です。

def mMatch(s: String) = {
    val target: String = "a"
    s match {
        case `target` => println("It was" + target)
        case _ => println("It was something else")
    }
}

def mMatch2(s: String) = {
    val Target: String = "a"
    s match {
        case Target => println("It was" + Target)
        case _ => println("It was something else")
    }
}

囲んでいるスコープにすでに存在する変数を誤って参照することを避けるために、デフォルトの動作は小文字パターンが変数であり、安定した識別子ではないことは理にかなっていると思います。大文字で始まるもの、またはバックティックで始まるものを見る場合にのみ、それが周囲のスコープから来ることを認識する必要があります。

202
Ben James