有人可以解释为什么在 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)
这是预期的行为吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
首先,您应该使用 foreach,而不是 map,但您已经知道了:-)
您正在尝试创建一个 Unit 数组的数组,该数组在 java 中被转换为 Void.TYPE。这会导致 IllegalArgumentException。
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.
Scala 使用
java.lang.reflect.Array.newInstance
在调用map
时动态创建数组。此方法,不接受大小为零。因为,您的 lambda 返回一个Array[Unit]
类型的空数组,其大小为零,因此在调用外部映射时会出现异常。顺便说一下,在在这个例子中,你确实应该使用
foreach
因为你不是试图将数组映射到另一个数组,而是使用副作用:编辑: 我误解了这个问题(参见MatthieuF 回答)。问题不在于数组的大小,而在于类型。只需使用以下命令即可重现该问题:
Scala use
java.lang.reflect.Array.newInstance
to create arrays dynamically whenmap
is called.This method, does not accept a size of zero. since, your lambda is returning an empty array of typeArray[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: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: