match式

2019年5月6日
1 分

match 式は、値のパターンマッチによって処理を分岐する構文(式)だ。

基本的な使い方

まずはいちばん基本的な、switch 文のような使い方。

scala> val name = "Taro"  
name: String = Taro  
  
scala> name match {  
     |     case "Taro" => "male"  
     |     case "Jiro" => "male"  
     |     case "Hanako" => "female"  
     | }  
res0: String = male

変数 name の値によって分岐している。キーワード match を対象となる変数の後に書くのが特徴的だな。res0 とあるように、match 式も値を返す。

match の対象には String 型じゃなく、ほかの型も使える。

scala> val n = 5  
n: Int = 5  
  
scala> n match {  
     |     case 1 => "one"  
     |     case 2 => "two"  
     |     case 3 => "three"  
     |     case _ => "many"  
     | }  
res1: String = many

最後の case_ は、ワイルドカードパターンといって、どんな値にもマッチする。Scala では分岐の漏れを防ぐためによく使われるようだ。

パターンをまとめる

複数のパターンで同じ処理をしたいときには、| で区切ってパターンを並べることでまとめることができる。こんなふうに。

scala> "def" match {  
     |     case "abc" | "def" =>  
     |         println("first")  
     |         println("second")  
     |     case "ghi" =>  
     |         println("third")  
     | }  
first  
second

ここで気が付いたけど、分岐先が複数の式になってても { } で囲う必要はないんだな。

パターンマッチによる値の取り出し

パターンに一種の変数を使うことで、対応する値を取り出すことができる。

scala> val lst = List("A", "B", "C")  
lst: List[String] = List(A, B, C)  
  
scala> lst match {  
     |     case List("A", b, c) =>  
     |         println("b = " + b)  
     |         println("c = " + c)  
     |     case _ =>  
     |         println("nothing")  
     | }  
b = B  
c = C

この例では、先頭が “A” であるような3要素のリストにマッチし、2番目と3番目の要素がそれぞれ bc に代入されている。

ガード式

パターンにガード式をつけることで、条件を加えることができる。たとえば、「先頭が “A” のリストで、かつ、2番目が “B” でない」というパターンは次のように書ける。

scala> lst match {  
     |     case List("A", b, c) if b != "B" =>  
     |         println("b = " + b)  
     |         println("c = " + c)  
     |     case _ =>  
     |         println("nothing")  
     | }  
nothing

この例では、「先頭が “A” のリスト」にはマッチするけど「if b != "B"」が偽になるので最初のパターンにはマッチせず、あとのワイルドカードパターンにマッチして nothing が返ってきている。

asパターン

パターンの前に変数名と @ をつけることで、パターンにマッチした値を変数に束縛(「束縛」って用語を使ってるな)することができる。これは後からパターンの値を参照するのに便利。

scala> val lst2 = List(List("A"), List("B", "C"))  
lst2: List[List[String]] = List(List(A), List(B, C))  
  
scala> lst2 match {  
     |     case List(a@List("A"), x) =>  
     |         println(a)  
     |         println(x)  
     |     case _ =>  
     |         println("nothing")  
     | }  
List(A)  
List(B, C)

ここでは、List("A") というパターンの値を変数 a に束縛して後から使っている。

というところで、とりあえずはここまで。