2012-02-22 6 views
3

まず。次のコードを検討してください。scalacが追加/ラッピングクロージャを生成する理由

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) 

foreachと例外の間に追加のanonfunがあります。 1つはfail(クラスFunction1 [])のオブジェクトですが、2番目の値はどこから来るのでしょうか?

foreach署名は、この機能を取ります

def foreach[U](f: A => U): Unit 

だから、何が第二1の目的は?彼らは本当に必要ない...二つの追加anonfunsあり

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) 

第二には、次のコードを考えてみ? :-E

+0

Scalaバージョン2.9.2.rdev-2769-2011-12-13-g2dd83da(Java HotSpot(TM)64ビットサーバーVM、Java 1.6.0_25)。 – tuxSlayer

答えて

4

バイトコードを見てみましょう。

object ExtraClosure { 
    val fail = (x: Any) => { throw new RuntimeException } 
    List(1).foreach(fail) 
} 

我々は(シングル)匿名関数の内部で、見つける:

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 

だからそれは結局、実際に余分な閉鎖ではありません。 1つのメソッドに2つの異なる戻り値がオーバーロードされています(これは、すべてのパラメーターの型を関数シグニチャーの一部として扱うため、JVMでは完全に問題ありません)。関数は汎用的なので、オブジェクトの戻り値を取らなければなりませんが、あなたが書いたコードは具体的にはNothingを返します。また、期待する型を返すメソッドを作成します。

これにはさまざまな方法がありますが、欠点がないものはありません。しかし、これはJVMが非常にうまくいくタイプのものですが、私はあまり心配しません。

編集:もちろん、2番目の例ではdefを使用し、anonfunは、defを関数オブジェクトにラップするクラスです。それはもちろんforeachFunction1になるので必要です。あなたは何とかそれを生成する必要がありますFunction1

+0

ああ...そうだ。しかし、このような生成を避けるためには、foreach()のパラメータとして(f:A => Any)を使用するほうがよいでしょう。 – tuxSlayer

+0

@tuxSlayer - それでもやりません。 'A => Any'は' Object => Object'に消去されます。これは既に使用されているものです。 –

+0

ああ... :)それを得る – tuxSlayer

関連する問題