2009-11-09 4 views
8

Warum optimiert scalac (der Scala Compiler) die Tail-Rekursion nicht?Warum kann Scalac die Tail-Rekursion in bestimmten Szenarien nicht optimieren?

-Code und Compiler Anrufungen, die dies zeigt:

 
> cat foo.scala 
class Foo { 
def ifak(n: Int, acc: Int):Int = { 
    if (n == 1) acc 
    else ifak(n-1, n*acc) 
} 
} 

> scalac foo.scala 
> jd-gui Foo.class 
import scala.ScalaObject; 

public class Foo 
    implements ScalaObject 
{ 
    public int ifak(int n, int acc) 
    { 
    return ((n == 1) ? acc : 
     ifak(n - 1, n * acc)); 
    } 
} 
+1

Beachten Sie, dass JVM-level-Rückstandsoptimierung für Java 7 beigetragen wird, siehe http://wikis.sun.com/display/mlvm/TailCalls –

Antwort

12

Methoden, die nicht Schwanz rekursiv sein kann außer Kraft gesetzt werden kann. Versuchen Sie folgendes:

class Foo { 
    private def ifak(n: Int, acc: Int): Int = { 
    if (n == 1) acc 
    else ifak(n-1, n*acc) 
    } 
} 
+0

+1 Was ist der Grund? (Ich meine, ich kann es mir vorstellen, aber ich würde gerne wissen) – OscarRyz

+2

@OscarRyz: siehe http://stackoverflow.com/questions/4785502/why-wont-the-scala-compiler-apply-tail-call-optimization- es sei denn, eine Methode ist fina –

1

Try this:

class Foo { 
    def ifak(n: Int, acc: Int):Int = { 
    if (n == 1) acc 
    else ifak(n-1, n*acc) 
    } 
} 

class Bar extends Foo { 
    override def ifak(n: Int, acc: Int): Int = { 
    println("Bar!") 
    super.ifak(n, acc) 
    } 
} 

val foobar = new Bar 
foobar.ifak(5, 1) 

Beachten Sie, dass ifak rekursiv sein kann, aber es kann nicht so gut. Markieren Sie die Klasse oder die Methode final und es wird wahrscheinlich tail-rekursiv gemacht.

0

Innere Funktionen sind ebenfalls für TCO geeignet.