3

Here's a copy of the interpreter commands:

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)

Is this expected behaviour?

Henry Henrinson
  • 5,203
  • 7
  • 44
  • 76

2 Answers2

5

First things first, you should be using foreach, not map, but you already knew that :-)

You are trying to create an array of array of Unit, which gets translated into Void.TYPE in java. This results in the IllegalArgumentException.

Matthew Farwell
  • 60,889
  • 18
  • 128
  • 171
3

Scala use java.lang.reflect.Array.newInstance to create arrays dynamically when map is called. This method, does not accept a size of zero. since, your lambda is returning an empty array of type Array[Unit], which as a size of zero, you get the exception, when calling the outer map.

By the way, in this example, you really should use foreach since you are not trying to map the array to another array, but rather to use side-effects:

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

scala> result
res21: Int = 3

Edit: I misunderstood the problem (See MatthieuF answer). The problem is not the size of the array but the type. It is possible to reproduce the problem with just:

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)
...
paradigmatic
  • 40,153
  • 18
  • 88
  • 147