2013-07-24 8 views
6

この暗黙的なvalによってStackOverFlowErrorがどのように発生しますか?スカラー暗黙の原因StackOverflowError

(まだエラーを引き起こすことが、私の元のコードを下に切り詰め)

object Complicit { 
    // a class with name, default, and conversion function as implicit val 
    case class CC[A](name: String, defaultValue: A)(implicit val convert: String => A) { 
    def getFrom(s: String): A= try { 
     convert(s) 
    } catch { 
     case t: Throwable => 
     println("ERROR: %s".format(t)) // just to see the StackOverflowException 
     defaultValue 
    } 
    } 

    // this works fine 
    object Works { 
    val cc1= CC("first", 0.1)(_.toDouble) 
    } 

    // this causes java.lang.StackOverflowError due to the implicit 
    object Fails { 
    // !!! StackOverFlowError here 
    implicit val stringToDouble: String => Double= { _.toDouble } 

    val cc2= CC("second", 0.2) 
    } 

    def main(args: Array[String]) { 
    // this works 
    println("%s %f".format(Works.cc1.name, Works.cc1.getFrom("2.3"))) 
    // this fails 
    println("%s %f".format(Fails.cc2.name, Fails.cc2.getFrom("4.5"))) 
    } 
} 

私は暗黙で違法な何かをやっていますか?

答えて

9

私はここで起こっていることに答えることができると信じています。それは他の暗黙的なコンバージョンとあなたが作成したものに関連しています。あなたはこのトレースを追加する場合は、オーバーフローが通常に関連するスタック何を確認することができます - Javaのクラッシュのスタック空間まで、繰り返し自分自身を呼び出す機能:

implicit val stringsToDouble: String => Double= { x=>println("called inner "+x); x.toDouble } 

....インナーと呼ばれる内部4.5 と呼ばれる内部4.5 呼ば 内側の4.5 と呼ばれる内部4.5ERROR呼ば4.5 : - 、(またはtoDouble Java文字列の天然の機能ではなく、むしろStringOpsで暗黙的な変換を使用して発生した糸状私は何が起こっているかと思いますjava.lang.StackOverflowErrorを

が、これがあります私は本当に確実ではないが同じ問題だ)。

したがって、toDoubleを呼び出すと、コンパイラは "toDouble"という関数を含む暗黙の変換を求めます。理論的にはそれはどんな結果のクラスでもあり得る。

しかし、いくつかの暗黙的な変換でこれを達成できたらどうなるでしょうか?残念ながら、「Double」には、ここで証明されたtoDouble関数も含まれています:

val x = 44.4 
x.toDouble 

と推測します。つまり、範囲内で最近接近した新しい暗黙の関数がコンテストに勝利し、 "toDouble"を達成するために円で呼び出されます。つまり、DoubleをDoubleクラスで繰り返し呼び出すために、文字列をdoubleに変更しようとします。私はそれがかなり混乱していると認めますが、証拠は合っています。

ここは修正です。説明に合っており、再帰呼び出しを防止します。

implicit val stringsToDouble: String => Double= { java.lang.Double.parseDouble(_) } 
+0

提出する価値のあるバグは誰にも分かりますか?私には暗黙の変換の範囲があり、その変換の定義コード内では有効ではないはずです。 (従って、常に除外される)。これを可能にすることができる唯一の結果は、常に無限ループになります – LaloInDublin

+0

私はこれがアドレッシングになる可能性があるチャンスを取って問題を提出しました.. Scala Programming Language/SI-7693 – LaloInDublin

+0

(バグではなく)何をするように求められたのかだけでした。問題を提出し、何が起こるかを確認するのは良いことです。たぶん、ユーザーを検出して警告する巧妙な方法があります。しかし、問題は再帰の前にコードの量と複雑さがあることです。また、誰かがその再帰を望み、終了条件をコーディングした可能性があります。 – Core

関連する問題