有人可以解释为什么在 Scala 中应用这样的映射会抛出 IllegalArgumentException 吗?

发布于 2024-11-28 13:25:17 字数 2141 浏览 1 评论 0原文

这是解释器命令的副本:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

药祭#氼 2024-12-05 13:25:17

首先,您应该使用 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.

不爱素颜 2024-12-05 13:25:17

Scala 使用 java.lang.reflect.Array.newInstance 在调用 map 时动态创建数组。 此方法,不接受大小为零。因为,您的 lambda 返回一个 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)
...

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)
...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文