当在对象上定义但不在类上定义时,方法是尾递归的

发布于 2024-10-12 07:11:49 字数 2569 浏览 2 评论 0原文

在对象上定义递归方法:

object Recursive {
    def recurse(maxDepth: Int = 10): Unit = {
        if (maxDepth == 0) throw new Exception
        recurse(maxDepth - 1)
    }
}

给出:

scala> Recursive.recurse(10)
java.lang.Exception
        at Recursive$.recurse(<console>:7)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:9)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$scala_repl_result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
        at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$17.apply(Interpreter.scala:988)
        at scala.util.control.Exception$Catch.apply(Exception.scal...

但在类上定义递归方法:

class Recursive {
    def recurse(maxDepth: Int = 10): Unit = {
        if (maxDepth == 0) throw new Exception
        recurse(maxDepth - 1)
    }
}

给出:

scala> new Recursive recurse(10)
java.lang.Exception
        at Recursive.recurse(<console>:7)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:9)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$scala_repl_result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcc..

方法是相同的。为什么在类上定义时不是尾递归?

Defining a recursive method on an object:

object Recursive {
    def recurse(maxDepth: Int = 10): Unit = {
        if (maxDepth == 0) throw new Exception
        recurse(maxDepth - 1)
    }
}

gives:

scala> Recursive.recurse(10)
java.lang.Exception
        at Recursive$.recurse(<console>:7)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:9)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$scala_repl_result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.tools.nsc.Interpreter$Request$anonfun$loadAndRun$1$anonfun$apply$17.apply(Interpreter.scala:988)
        at scala.tools.nsc.Interpreter$Request$anonfun$loadAndRun$1$anonfun$apply$17.apply(Interpreter.scala:988)
        at scala.util.control.Exception$Catch.apply(Exception.scal...

But defining it on a class:

class Recursive {
    def recurse(maxDepth: Int = 10): Unit = {
        if (maxDepth == 0) throw new Exception
        recurse(maxDepth - 1)
    }
}

gives:

scala> new Recursive recurse(10)
java.lang.Exception
        at Recursive.recurse(<console>:7)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at Recursive.recurse(<console>:8)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:9)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$scala_repl_result(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcc..

The methods are identical. Why is it not tail recursive when defined on a class?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不奢求什么 2024-10-19 07:11:49

如果您希望执行尾递归,则不能覆盖recurse。如果 recurse 是可重写的,如在 class 声明中那样,则其中的任何递归都必须使用动态方法调用(因为它可能是多态的),这无法优化为goto 风格的语句。

object 单例声明静态地确保对递归的明确调用,并让编译器继续进行尾递归优化。

If you want tail-recursion to be performed, recurse can not be overridable. If recurse is overridable, as in your class declaration, any recursion within it has to use dynamic method invocation (because it is potentially polymorphic), which can not be optimized to a goto-style statement.

The object singleton declaration statically ensures the unambiguous call to recurse, and lets the compiler proceed with tail recursion optimization.

作业与我同在 2024-10-19 07:11:49

如果您希望某个方法是尾递归的,则应该使用 @tailrec 对其进行注释。如果编译器无法应用 TCO,则会出错。

scala> import annotation._                           
import annotation._

scala> class Recursive {                                     
     |     @tailrec def recurse(maxDepth: Int = 10): Unit = {
     |         if (maxDepth == 0) throw new Exception        
     |         recurse(maxDepth - 1)                         
     |     }                                                 
     | }
<console>:12: error: could not optimize @tailrec annotated method: it is neither private nor final so can be overridden
           @tailrec def recurse(maxDepth: Int = 10): Unit = {
                        ^

If you expect a method to be tail recursive, you should annotate it with @tailrec. If the compiler can't apply TCO, it will error.

scala> import annotation._                           
import annotation._

scala> class Recursive {                                     
     |     @tailrec def recurse(maxDepth: Int = 10): Unit = {
     |         if (maxDepth == 0) throw new Exception        
     |         recurse(maxDepth - 1)                         
     |     }                                                 
     | }
<console>:12: error: could not optimize @tailrec annotated method: it is neither private nor final so can be overridden
           @tailrec def recurse(maxDepth: Int = 10): Unit = {
                        ^
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文