为什么在使用隐式转换时出现无限循环? [英] Why do I get an infinite loop when using implicit conversions?

查看:78
本文介绍了为什么在使用隐式转换时出现无限循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上下文

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,最终得到了这段代码.它可以编译并运行,但是...

Explanation I was playing with Scala and ended up with this code. It compiles and runs, but...

问题:

1)两者之间是否有任何区别(可读性,性能,已知的错误等)

1) Is there any difference (readbility, performance, known bugs, anything) between

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

case `functional` => functional(n)

这应该是更多的讨论,所以我不仅对事实感兴趣.欢迎任何意见.

This is supposed to be more of a discussion, so I'm not only interested in facts. Any opinion is welcomed.

2)查看fibonacci方法的第一行.在这里:

2) Look at the first line of the fibonacci method. Here it is:

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

如果我省略第二个参数列表(imperativeWithLoop),则代码会编译,但是在运行它时会进入无限循环.有人知道为什么吗?编译器知道默认的实现imperativeWithLoop(不会产生错误).那么为什么不隐式调用它呢? (我认为不是)

If I leave the 2nd parameter list (imperativeWithLoop) out, the code compiles but enters an infinite loop when I run it. Does anyone know why? The default implementation imperativeWithLoop is known to the compiler (no errors are produced). So why doesn't it get implicitly invoked? (I assume it doesn't)

推荐答案

关于第一个问题,存在微小差异,但在此无所谓.但是最好将对象大写,在这种情况下,您可以这样编写:

Regarding the first question, there are small differences, but none that matter here. But it would be better if you uppercased the objects, in which case you could write this:

case Functional => Functional(n)

关于第二个问题,如果省略imperativeWithLoop,它将选择作用域中最接近的隐式Fibonacciimplementation(已经发现它等于funcional).因此,它将使用与之前调用的参数完全相同的参数进行调用,从而进入无限循环.

Regarding the second question, if you leave out imperativeWithLoop, it will select the implicit Fibonacci closest in scope -- implementation (which has already be found to be equal to funcional). So it will call itself with the exact same parameters as it had called before, and, therefore, enter an infinite loop.

这篇关于为什么在使用隐式转换时出现无限循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆