kmizuの日記

プログラミングや形式言語に関係のあることを書いたり書かなかったり。

ひょっとしたら役に立つかもしれないScala Tips(2) - パターンマッチングの最適化 -

Scalaのパターンマッチングを用いたコードは、通常は

if(...) {
  ...
} else if(...) {
  ...
}

のような、上から順に条件を満たしているかをチェックして分岐するコードにコンパイルされるが、色々試して見たところ、整数を対象にしたパターンマッチングの場合、switch-caseに相当するコードにコンパイルしてくれるようだ。例えば、次のようなコードをコンパイルすると

object PatternMatching {
  def main(args: Array[String]) {
    args(0).toInt match {
      case 1 => println("A")
      case 2 => println("B")
    }
  }
}

mainメソッドのバイトコードは以下のようになり(javap -cした結果)、tableswitch(Javaのswitch文を実装するのに通常使われる命令。類似の命令として、lookupswitchがある)を使ったコードにコンパイルされていることがわかる。

   0:	getstatic	#25; //Field scala/Predef$.MODULE$:Lscala/Predef$;
   3:	aload_1
   4:	iconst_0
   5:	aaload
   6:	invokevirtual	#29; //Method scala/Predef$.stringWrapper:(Ljava/lang/String;)Lscala/runtime/RichString;
   9:	invokevirtual	#35; //Method scala/runtime/RichString.toInt:()I
   12:	istore_2
   13:	iload_2
   14:	tableswitch{ //1 to 2
		1: 48;
		2: 59;
		default: 36 }
   36:	new	#37; //class scala/MatchError
   39:	dup
   40:	iload_2
   41:	invokestatic	#43; //Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer;
   44:	invokespecial	#46; //Method scala/MatchError."<init>":(Ljava/lang/Object;)V
   47:	athrow
   48:	getstatic	#25; //Field scala/Predef$.MODULE$:Lscala/Predef$;
   51:	ldc	#48; //String A
   53:	invokevirtual	#51; //Method scala/Predef$.println:(Ljava/lang/Object;)V
   56:	goto	67
   59:	getstatic	#25; //Field scala/Predef$.MODULE$:Lscala/Predef$;
   62:	ldc	#53; //String B
   64:	invokevirtual	#51; //Method scala/Predef$.println:(Ljava/lang/Object;)V
   67:	return