2009-11-09 27 views
8

Tại sao scalac (trình biên dịch Scala) tối ưu hóa đệ quy đuôi?Tại sao scalac không thể tối ưu hóa đệ quy đuôi trong các tình huống nhất định?

Mã và trình biên dịch lời gọi đó chứng tỏ điều này:

 
> 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

lưu ý rằng tối ưu hóa tailcall cấp JVM được đóng góp cho java 7 xem http://wikis.sun.com/display/mlvm/TailCalls –

Trả lời

12

Các phương pháp có thể được ghi đè KHÔNG có thể đệ quy đuôi. Hãy thử điều này:

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

+1 Lý do cơ bản là gì? (Tôi có nghĩa là tôi có thể tưởng tượng nó, nhưng tôi muốn biết) – OscarRyz

+2

@OscarRyz: xem http://stackoverflow.com/questions/4785502/why-wont-the-scala-compiler-apply-tail-call-optimization- trừ khi-một-phương pháp-là-fina –

1

Hãy thử điều này:

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) 

ý rằng ifakthể được đệ quy, nhưng nó có thể không phải là tốt. Đánh dấu lớp hoặc phương thức cuối cùng, và nó có lẽ sẽ làm cho đệ quy đuôi.

0

Chức năng bên trong cũng đủ điều kiện cho TCO.

Các vấn đề liên quan