上下文
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
}
说明 我正在使用 Scala,最终得到了这段代码。它编译并运行,但是...
问题:
1) 之间有什么区别(可读性、性能、已知错误等)
case f: functional.type => f(n)
和
case `functional` => functional(n)
这应该是更多的讨论,所以我不仅仅对事实感兴趣。欢迎任何意见。
2) 查看fibonacci
方法的第一行。这是:
case f: functional.type if n > Threshold => fibonacci(n)(imperativeWithLoop)
如果我保留第二个参数列表(imperativeWithLoop)
,代码会编译,但在运行时会进入无限循环。有谁知道为什么?编译器已知默认实现imperativeWithLoop
(不会产生错误)。那么为什么它不被隐式调用呢? (我认为不会)
最佳答案
关于第一个问题,存在一些细微的差异,但这里并不重要。但如果你将对象大写会更好,在这种情况下你可以这样写:
case Functional => Functional(n)
关于第二个问题,如果你省略了imperativeWithLoop
,它会选择范围内最接近的隐式Fibonacci
——implementation
(它有已经被发现等于funcional
)。因此它将使用与之前调用完全相同的参数来调用自身,从而进入无限循环。
关于scala - 为什么使用隐式转换时会出现无限循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6618835/