2012年9月11日火曜日

[Scala] シーケンスのマッチ

List などシーケンス(Seq)のマッチを見てみよう。
Tuple と同様に型や出現位置によってマッチングを行い、変数への値の設定が行われる。
Tuple と違って List は可変長なので各 case 句の要素数の違いによるマッチもできる。

要素の数によるマッチ
val aList = List(1, 2, 3)
aList match {
  case List(x,y) => println("Mathed (x,y)=" + (x,y))
  case List(x,y,z) => println("Mathed (x,y,z)=" + (x,y,z))
  case _ => println("OTHER")
}

Mathed (x,y,z)=(1,2,3)

要素の型によるマッチ
val aList = List("ONE", 1);
aList match {
  case List(x : Int, y) => println("Int (x,y)=" + (x,y))
  case List(x : String, y) => println("String (x,y)=" + (x,y))
  case _ => println("OTHER");
}

String (x,y)=(ONE,1)

要素の値によるマッチ
val aList = List("ONE", "TWO")
aList match {
  case List("AAA", y) => println("AAA y=" + y)
  case List("ONE", y) => println("ONE y=" + y)
  case _ => println("OTHER")
}

ONE y=TWO



入れ子の要素のマッチ


List の要素に List や Tuple があった場合のマッチ動作を見てみる。

val aList = List("ONE", List("TWO", "THREE"))
aList match {
  case List(x, List(y,z)) => println("(x,y,z) = " + (x,y,z))
  case _ => println("OTHER")
}
val aList2 = List("ONE", ("TWO", "THREE"))
aList2 match {
  case List(x, (y,z)) => println("(x,y,z) = " + (x,y,z))
  case _ => println("OTHER")
}

(x,y,z) = (ONE,TWO,THREE) (x,y,z) = (ONE,TWO,THREE)

要素が List や Tuple の場合の入れ子になっている要素に対してもマッチできる。


残りの要素の取得


List は可変長なので実行時まで実際の要素数はわからない。前のほうの要素でマッチさせてあとは何でもよい場合には、「 _* 」を使ってマッチさせる。

val aList = List("ONE", "TWO", "THREE", "FOUR")
aList match {
  case List(x, "TWO", _*) => println("x=" + x)
  case _ => println("OTHER")
}

x=ONE

「要素の2番目が "TWO" だったら先頭の要素を取得する」という動作になっている。
残りの部分を取得したい場合には @ で代入する変数名を指定することができる。

val aList = List("ONE", "TWO", "THREE", "FOUR");
aList match {
  case List(x, "TWO", z@_*) => println("(x,z) = " + (x,z))
  case _ => println("OTHER");
}

(x,z) = (ONE,List(THREE, FOUR))

3番目以降の要素が変数 z に List として設定されている。


:: によるマッチ


List の場合には、「 :: 」 を使って先頭の要素とそれ以外に分解することができる。

val aList = List("ONE", "TWO", "THREE", "FOUR")
aList match {
  case x :: y => println("(x,y) = " + (x,y)
  case _ =gt; println("OTHER")
}

(x,y) = (ONE,List(TWO, THREE, FOUR))

x に先頭の要素が、y に残りの要素が格納されている。
これは先ほどの要素の残りとマッチする構文で以下のように書いたのと同じことになる。

val aList = List("ONE", "TWO", "THREE", "FOUR")
aList match {
  case List(x, y@_*) => println("(x,y) = " + (x,y))
  case _ => println("OTHER")
}

(x,y) = (ONE,List(TWO, THREE, FOUR))



0 件のコメント:

コメントを投稿