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) 

如果我離開的第二個參數列表(imperativeWithLoop)出來,代碼編譯,但是當我運行它進入無限循環。有誰知道爲什麼?編譯器已知缺省實現imperativeWithLoop(不產生錯誤)。那爲什麼它不被隱式調用呢? (我認爲它不)

回答

3

關於第一個問題,有一些小的差異,但這裏沒有關係。但它會更好,如果你大寫的對象,在這種情況下,你可以這樣寫:

case Functional => Functional(n) 

關於第二個問題,如果你離開了imperativeWithLoop,它會選擇隱Fibonacci最接近的範圍 - implementation(已經發現它等於funcional)。所以它會用自己以前所稱的完全相同的參數來調用它自己,並因此進入一個無限循環。

+1

Thx,我想我現在就明白了。在這種情況下,編譯器警告或其他東西會很好。 – agilesteel

相關問題