The recursive tail method when defining an object, but not a class

Defining a recursive method for 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 in 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 a recursive tail, if defined in a class?

+8
scala recursion
source share
2 answers

If you want to perform tail recursion, recurse cannot be overridden. If recurse is recurse , as in your class declaration, any recursion inside it should use a dynamic method call (because it is potentially polymorphic), which cannot be optimized for the goto-style statement.

The singleton object declaration statically provides a unique call for recursion and allows the compiler to continue tail recursion optimization.

+16
source share

If you expect the method to be recursive with a tail, you should annotate it with @tailrec . If the compiler cannot apply TCO, this will result in an 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 = { ^ 
+10
source share

Source: https://habr.com/ru/post/651096/


All Articles