2012年9月7日金曜日

[Scala] match (Tuple編)

Tuple に対する match...case のパターンマッチを見てみる。これがかなりに強力。
引数の型や数によってマッチする case 節を判定し、マッチした case 節の変数に値を割り当ててくれる。

val list1 : List[Any] = List(
    ("one", 1), (2, 2), ("three", "tri", 3) );

for (elem <- list1) {
  elem match {
    case (v1: String, v2:Int) => 
        println("[String, Int]: " + v1 + ", " + v2);
    case (v1: Int, v2:Int) => 
        println("[Int, Int]: " + v1 + ", " + v2);
    case (v1, v2, v3) => 
        println("[Triple]: " + v1 + ", " + v2 + ", " + v3);
    case _ => println("OTHER");
  }
}

[String, Int]: one, 1 [Int, Int]: 2, 2 [Triple]: three, tri, 3

一部に値を与えておけば、それも考慮してマッチが行われる。

val list2 : List[Any] = List(
    ("one", 1), ("two", 2));

for (elem <- list2) {
  elem match {
    case ("one", value) => println("one is " + value );
    case (value, 2) => println("2 is " + value );
    case _ => ;
    }
} 

one is 1 2 is two

値を与える個所は何番目のパラメータでも構わない。

前回書いた if 句(ガード)も併用すればかなり複雑なことでも case 節で記述できると思う。


Tuple マッチで使えるTupleの記法


Tutle2 の生成はいくつかの方法で記述できる。
(x, y)、Tuple2(x, y)、Pair(x, y)、x->y、new Tuple2(x,y)。
どれが使えるか試してみよう。

普通に使えたのは (x, y)、Tuple2(x, y)、Pair(x, y)。

    val tuple = "one" -> 1;
    tuple match {
      case (x:String, y:Int) => 
        println("matched x: [" + x + "] y: [" + y + "]");
      case _  => println("Not Matched");
    }
    tuple match {
      case Tuple2(x:String, y:Int) => 
        println("matched x: [" + x + "] y: [" + y + "]");
      case _  => println("Not Matched");
    }
    tuple match {
      case Pair(x:String, y:Int) =>
        println("matched x: [" + x + "] y: [" + y + "]");
      case _  => println("Not Matched");
    }

matched x: [one] y: [1] matched x: [one] y: [1] matched x: [one] y: [1]

使えなかったのは x->y、new Tuple2(x,y)。

    tuple match {
      case (x:String -> y:Int) => println("matched");
      case _  => println("Not Matched");
    }
    tuple match {
      case new Tuple2(x:String, y:Int) => println("matched");
      case _  => println("Not Matched");
    }

- ')' expected but identifier found. - type mismatch; found : String required: (java.lang.String, Int) - pattern type is incompatible with expected type; found : String required: (java.lang.String, Int) - ')' expected but identifier found. - '=>' expected but ';' found. - illegal start of simple pattern - illegal start of simple pattern

変数への割り当てをやめて直接値を記述してもエラーになる。

    tuple match {
      case ("one" -> 1) => println("matched");
      case _  => println("Not Matched");
    }
    tuple match {
      case new Tuple2("one", 1) => println("matched");
      case _  => println("Not Matched");
    }

not found: value -> - '=>' expected but ';' found. - illegal start of simple pattern - illegal start of simple pattern

こういうものらしい。

case の後ろにかけるのは 直接 apply を呼び出すものに限られるのだろうか?
「 -> 」 呼び出しは、最終的には Tuple2.apply になるのだが、 ArrowAssoc クラスの -> が呼び出されたりしているので使えないということになっているのではないかと思う。


0 件のコメント:

コメントを投稿