2011-08-08 4 views
3

はインタプリタコマンドのコピーです:Scalaでこのようなマップを適用する理由とIllegalArgumentExceptionを説明できる人はいますか?ここ

scala>val myTable = Array(Array(1)) 
res30: Array[Array[Int]] = Array(Array(1)) 

scala> myTable.map(_.map(_.toString)) 
res31: Array[Array[java.lang.String]] = Array(Array(1)) 

scala> var result = 0 
result: Int = 0 

scala> myTable.head 
res32: Array[Int] = Array(1) 

//note how applying this works 
scala> res32.map(elem => if(3> result) result = 3) 
res34: Array[Unit] = Array(()) 

scala> result 
res35: Int = 3 

//this also works 
scala> myTable.map(_.map(_.toString)) 
res31: Array[Array[java.lang.String]] = Array(Array(1)) 

//when you combine the double map application and the anonymous function from earlier: 
scala> myTable.map(_.map(elem => if(3 > result) result = 3)) 
java.lang.IllegalArgumentException 
    at java.lang.reflect.Array.newArray(Native Method) 
    at java.lang.reflect.Array.newInstance(Array.java:52) 
    at scala.reflect.ClassManifest$class.arrayClass(ClassManifest.scala:107) 
    at scala.reflect.Manifest$$anon$9.arrayClass(Manifest.scala:152) 
    at scala.reflect.Manifest$class.arrayManifest(Manifest.scala:46) 
    at scala.reflect.Manifest$$anon$9.arrayManifest(Manifest.scala:152) 
    at scala.reflect.Manifest$$anon$9.arrayManifest(Manifest.scala:152) 
    at scala.reflect.ClassManifest$.arrayType(ClassManifest.scala:205) 
    at .<init>(<console>:45) 
    at .<clinit>(<console>) 
at .<init>(<console>:11) 
at .<clinit>(<console>) 
at $export(<console>) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
at java.lang.reflect.Method.invoke(Method.java:597) 
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:592) 
at scala.tools.nsc.interpreter.IMain$Request$$anonfun$10.apply(IMain.scala:828) 
at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43) 
at scala.tools.nsc.io.package$$anon$2.run(package.scala:31) 
at java.lang.Thread.run(Thread.java:662) 

は、この予想される動作ですか?

答えて

3

mapが呼び出されたときに、java.lang.reflect.Array.newInstanceを使用して動的に配列を作成します。 この方法、does not accept a size of zero。あなたのラムダがタイプArray[Unit]の空の配列を返しているからです。外側のマップを呼び出すときには、ゼロのサイズで例外が発生します。

scala> myTable.foreach(_.foreach(elem => if(3 > result) result = 3)) 

scala> result 
res21: Int = 3 

編集:方法、この例では、あなたが別の配列への配列をマッピングしようとしていないので、本当にforeachを使うべきではなく、副作用を使用することにより、

私は問題を誤解しました(MatthieuF答えを参照してください)。問題は配列のサイズではなくタイプです。あなたがマップ、foreachのを使用していないする必要があり、

scala> java.lang.reflect.Array.newInstance(classOf[Unit], 1) 
java.lang.IllegalArgumentException 
at java.lang.reflect.Array.newArray(Native Method) 
at java.lang.reflect.Array.newInstance(Array.java:52) 
at .<init>(<console>:8) 
... 
+0

はい(ゼロのサイズを受け入れます)。使用されるメソッドは次のとおりです。public static Object newInstance(Class componentType、int length)は、NegativeArraySizeExceptionをスローします。他の人はいません –

+0

はい、あなたは正しいです!私は両方の方法(と問題)を混ぜた。 – paradigmatic

+0

以下を試してください:java.lang.reflect.Array.newInstance(int.class、0) –

5

まず物事を最初に、しかし、あなたはすでにあなたがの配列を作成しようとしている

その:-)を知っていた:ちょうどで問題を再現することが可能ですユニットの配列。javaのVoid.TYPEに変換されます。この結果、IllegalArgumentExceptionが発生します。

関連する問題