1

コンテキスト暗黙の変換を使用すると無限ループに陥るのはなぜですか?

object Fibonacci { 
    final val Threshold = 30 

    def fibonacci(n: Int)(implicit implementation: Fibonacci): Int = implementation match { 
    case f: functional.type if n > Threshold => fibonacci(n)(imperativeWithLoop) 
    case f: imperativeWithRecursion.type => f(n) 
    case f: imperativeWithLoop.type => f(n) 
    case f: functional.type => f(n) 
    } 

    sealed abstract class Fibonacci extends (Int => Int) 

    object functional extends Fibonacci { 
    def apply(n: Int): Int = 
     if (n <= 1) n else apply(n - 1) + apply(n - 2) 
    } 

    object imperativeWithRecursion extends Fibonacci { 
    def apply(n: Int) = { 
     @scala.annotation.tailrec 
     def recursion(i: Int, f1: Int, f2: Int): Int = 
     if (i == n) f2 else recursion(i + 1, f2, f1 + f2) 

     if (n <= 1) n else recursion(1, 0, 1) 
    } 
    } 

    implicit object imperativeWithLoop extends Fibonacci { 
    def apply(n: Int) = { 
     def loop = { 
     var res = 0 
     var f1 = 0 
     var f2 = 1 
     for (i <- 2 to n) { 
      res = f1 + f2 
      f1 = f2 
      f2 = res 
     } 
     res 
     } 

     if (n <= 1) n else loop 
    } 
    } 
} 

object Main extends App { // or REPL 
    import Fibonacci._ 
    println(fibonacci(6)(imperativeWithRecursion)) // 8 
    println(fibonacci(6)(imperativeWithLoop)) // 8 
    println(fibonacci(6)(functional)) // 8 
    println(fibonacci(6)) // 8 
    println(fibonacci(40)(functional)) // 102334155 
} 

説明 私はスカラ座で遊んと、このコードで終わりました。これは、コンパイルし、実行されますが、...

質問:

1)

case f: functional.type => f(n) 

case `functional` => functional(n) 
との差額(readbility、パフォーマンス、既知のバグ、何が)あります

これはもっと議論の場であると思われるので、私は事実だけに興味がありません。意見は歓迎されます。

2)fibonacciメソッドの最初の行を見てください。ここでは、次のとおりです。

case f: functional.type if n > Threshold => fibonacci(n)(imperativeWithLoop) 

私は2番目のパラメータリスト(imperativeWithLoop)のままにすると、コードがコンパイルされますが、私はそれを実行すると無限ループに入ります。なぜ誰が知っていますか?デフォルトの実装imperativeWithLoopはコンパイラに認識されています(エラーは生成されません)。ではなぜ暗黙のうちに呼び出されないのですか? (私はそうではないと仮定します)

答えて

3

最初の質問に関しては、小さな違いがありますが、ここでは重要ではありません。 - implementation(2番目の質問について

case Functional => Functional(n) 

あなたがimperativeWithLoopを残せば、それは範囲内の最も近い暗黙のFibonacciを選択します。しかし、あなたがこれを書くことができ、その場合には、オブジェクトを、大文字ならば良いだろうこれは既にfuncionalに等しいことが分かっている)。したがって、これまでと同じパラメーターで呼び出されるため、無限ループに入ります。

+1

Thx、私は今それを得ると思います。このような場合、コンパイラの警告や何かがうまくいくでしょう。 – agilesteel

関連する問題