1. ホーム
  2. scala

[解決済み] Scalaのパターンマッチはなぜ変数で機能しないのですか?

2022-08-11 05:11:17

質問

次のような関数を考えてみましょう。

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

これは、targetが実際には入力が何であれ割り当てたい名前であると考えるからでしょう。2つの質問があります。

  1. なぜこのような動作になるのでしょうか?case は適切な型を持つ既存の変数をスコープ内で探し、それらを最初に使用し、もし何も見つからなかったら target を patternmatch over するための名前として扱うことはできないのでしょうか?

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

どのように解決するのですか?

探しているのは 安定した識別子 . 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")
    }
}

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