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)