scalac为何生成附加/包装闭包
首先。考虑下面的代码scalac为何生成附加/包装闭包,scala,compiler-construction,closures,Scala,Compiler Construction,Closures,首先。考虑下面的代码 scala> val fail = (x: Any) => { throw new RuntimeException } fail: Any => Nothing = <function1> scala> List(1).foreach(fail) java.lang.RuntimeException at $anonfun$1.apply(<console>:7) at $anonfun$1.apply(&
scala> val fail = (x: Any) => { throw new RuntimeException }
fail: Any => Nothing = <function1>
scala> List(1).foreach(fail)
java.lang.RuntimeException
at $anonfun$1.apply(<console>:7)
at $anonfun$1.apply(<console>:7)
at scala.collection.LinearSeqOptimized$class.foreach(LinearSeqOptimized.scala:59)
那么,第二个的目的是什么
第二,考虑下面的代码:
scala> def outer() {
| def innerFail(x: Any) = { throw new RuntimeException("inner fail") }
|
| Set(1) foreach innerFail
| }
outer: ()Unit
scala> outer()
java.lang.RuntimeException: inner fail
at .innerFail$1(<console>:8)
at $anonfun$outer$1.apply(<console>:10)
at $anonfun$outer$1.apply(<console>:10)
at scala.collection.immutable.Set$Set1.foreach(Set.scala:86)
scala>def outer(){
|def innerFail(x:Any)={抛出新的运行时异常(“内部故障”)}
|
|设置(1)foreach innerFail
| }
外部:()单元
scala>outer()
java.lang.RuntimeException:内部失败
at.innerFail$1(:8)
在$anonfun$outer$1.应用(:10)
在$anonfun$outer$1.应用(:10)
位于scala.collection.immutable.Set$Set1.foreach(Set.scala:86)
还有两个额外的anonfuns。。。他们真的需要吗-让我们看看字节码
object ExtraClosure {
val fail = (x: Any) => { throw new RuntimeException }
List(1).foreach(fail)
}
我们发现,在(单个)匿名函数中:
def foreach[U](f: A => U): Unit
public final scala.runtime.Nothing$ apply(java.lang.Object);
Code:
0: new #15; //class java/lang/RuntimeException
3: dup
4: invokespecial #19; //Method java/lang/RuntimeException."<init>":()V
7: athrow
public final java.lang.Object apply(java.lang.Object);
Code:
0: aload_0
1: aload_1
2: invokevirtual #27; //Method apply:(Ljava/lang/Object;)Lscala/runtime/Nothing$;
5: athrow
public final scala.runtime.Nothing$apply(java.lang.Object);
代码:
0:新#15//类java/lang/RuntimeException
3:dup
4:特别是#19//方法java/lang/RuntimeException。“”:()V
7:athrow
公共最终java.lang.Object应用(java.lang.Object);
代码:
0:aload_0
1:aload_1
2:invokevirtual#27//方法apply:(Ljava/lang/Object;)Lscala/runtime/Nothing$;
5:athrow
所以这毕竟不是一个额外的结束。我们有一个方法重载了两个不同的返回值(这对于JVM来说是完全正确的,因为它将所有参数的类型作为函数签名的一部分)。函数是泛型的,因此它必须接受对象返回,但是您编写的代码专门返回Nothing
,它还创建了一个返回您期望的类型的方法
围绕这一点有各种各样的方法,但没有一种方法是没有缺点的。然而,JVM非常擅长避免这种情况,所以我不会太担心
编辑:当然,在第二个示例中,您使用了
def
,而anonfun
是将该def
包装到函数对象中的类。这当然是需要的,因为foreach
需要函数1
。您必须以某种方式生成Function1
。Scala版本2.9.2.rdev-2769-2011-12-13-g2dd83da(Java热点(TM)64位服务器虚拟机,Java 1.6.025)。哦。。。我懂了。但是使用(f:A=>Any)作为foreach()
的参数不是更好吗?以避免这样的生成。@tuxSlayer-这仍然不行A=>任何
都会被擦除到Object=>Object
,该对象已被使用。