Может кто-нибудь объяснить, почему применение карты как это в Scala бросков и IllegalArgumentException? - PullRequest
3 голосов
/ 08 августа 2011

Вот копия команд интерпретатора:

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)

Это ожидаемое поведение?

Ответы [ 2 ]

5 голосов
/ 08 августа 2011

Перво-наперво, вы должны использовать foreach, а не map, но вы уже знали, что: -)

Вы пытаетесь создать массив массивов Unit, который преобразуется в Void.TYPE в Java. Это приводит к IllegalArgumentException.

3 голосов
/ 08 августа 2011

Scala использует java.lang.reflect.Array.newInstance для динамического создания массивов при вызове map. Этот метод не принимает размер ноль . так как ваша лямбда возвращает пустой массив типа Array[Unit], который при нулевом размере вы получаете исключение при вызове внешней карты.

Кстати, в этом примере вам действительно следует использовать foreach, поскольку вы не пытаетесь сопоставить массив с другим массивом, а используете побочные эффекты:

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

scala> result
res21: Int = 3

Редактировать: Я неправильно понял проблему (см. MatthieuF ответ). Проблема не в размере массива, а в его типе. Можно воспроизвести проблему с помощью:

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)
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...