kmizuの日記

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

Function TypeとTuple Typeの制限

Scalaでは、function typeやtypeを表記するのに、

(Int) => Int (function type)

(Int, Int) (tuple type)

といった記法が使えて、一見すると、function typeやtuple typeが普通のクラス型と違う特別な型かのように見えるのだが、実はこれは、単なる

scala.Function1[Int, Int]

scala.Tuple2[Int, Int]

のシンタックスシュガーだったりする(この辺のことは、Scala勉強会@関東-1の資料でも書いたけど)。さて、ここでScalaのAPIリファレンスを見てみると、function typeはFunction22まで、tuple typeについてもTuple22までしか用意されていない。さて、それでは23個以上の引数を持つ関数(メソッドではない)や23個以上の要素を持つタプルを作ろうとするとどうなるのだろうか、というわけで試してみた(scala 2.7.1.final)。まずは、function typeについては、以下のように23個の引数を持つ無名関数を生成し、それを持ったobjectの定義をコンパイルしてみた。

object TooManyArgsFunction {
  val f = (a1:Int, a2:Int, a3:Int, a4:Int, a5:Int, a6:Int, a7:Int, a8:Int, 
           a9:Int, a10:Int, a11:Int, a12:Int, a13:Int, a14:Int, a15:Int, 
           a16:Int, a17:Int, a18:Int, a19:Int, a20:Int, a21:Int, a22:Int, 
           a23:Int) => 1
}

結果:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 23
	at scala.tools.nsc.typechecker.Typers$Typer.decompose$2(Typers.scala:1446)
	at scala.tools.nsc.typechecker.Typers$Typer.typedFunction(Typers.scala:1448)
	at scala.tools.nsc.typechecker.Typers$Typer.typed1(Typers.scala:3022)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:3228)
	at scala.tools.nsc.typechecker.Typers$Typer.typed(Typers.scala:3276)
	at scala.tools.nsc.typechecker.Typers$Typer.computeType(Typers.scala:3318)
	at scala.tools.nsc.typechecker.Namers$Namer.typeSig(Namers.scala:826)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$typeCompleter$1.apply(Namers.scala:404)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$typeCompleter$1.apply(Namers.scala:402)
...(長いので以下省略)

というわけで、コンパイラが落ちてしまった。どうも、境界チェックを忘れているっぽい。

tuple typeについても同様にして、試してみた。

object TooManyElementsTuple {
  val t = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
           1, 1, 1, 1, 1, 1, 1, 1)
}

結果:

TooManyElementsTuple.scala:2: error: value Tuple23 is not a member of package scala
  val t = (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 

          ^
one error found

tuple typeの方はちゃんとチェックされてるっぽい。

追記:せっかくなんで、バグ報告しといた(Ticket #944)