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


113

次の関数を取ります:

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ステートメントを使用できますが、マッチケースの方がエレガントです。



1
この質問、コード、回答はScala 2.12.xの時点で古くなっていると思います。該当するバージョンが質問の一部として言及されているとよいでしょう。
conny 2017年

回答:


217

あなたが探しているのは安定した識別子です。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")
    }
}

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


3
これは、変数が大文字で始まり記号が小文字で始まるErlangに由来するに違いない。
エミルイワノフ

11
お知らせtarget値であり、( val)、およびでない変数(var)。変数では機能しません。
Luigi Plinge、2011

大文字?FORTRANの色合い。弱い、マーティン、弱い。
Malvolio 2011

13
@Emil実際、Scalaの大文字の識別子は定数を示します。したがって、大文字の識別子でのパターンマッチングは、定数と比較することを意味します。それは本当の理由Nilだと私が思うのようなものを真剣に助けます。
ダニエルC.ソブラル

thisパターンマッチを行うための安定した識別子として使用することはできないようcase x if x == this =>です。おそらく構文上の制限です。それ以外の場合は、少なくともobjects 内で意味的に機能するはずです。
Nader Ghanbari、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.