2011-11-17 74 views
3

假設我有以下代碼在Scala中可以保證尾遞歸優化嗎?

def foo(x:Int):Unit = { 
    if (x == 1) println ("done") 
    else foo(scala.util.Random.nextInt(10)) 
} 

能夠保證所有的編譯器做尾遞歸優化?

+0

我不知道Scala保證你什麼,但是在JVM的一般情況下並不實現尾遞歸。 (對於tailrec調用沒有JVM字節碼) –

+0

@Basile Starynkevitch:Scala可以編譯簡單的尾循環遞歸循環。一些JVM支持「自動」尾部遞歸,但不幸的是Oracle不支持。 – Landei

回答

12

是的。要知道肯定添加@tailrec註釋您的方法。這會導致編譯器在使用尾遞歸進行編譯時發出錯誤。

@tailrec 
def foo(x:Int):Unit = { 
    if (x == 1) println ("done") 
    else foo(scala.util.Random.nextInt(10)) 
} 
+1

在Scala 2.8中,我必須執行'import scala.annotation.tailrec'。 – Jus12

+0

試着打破它。在方法的底部添加一個額外的(),以便在調用之後做些事情,但仍然返回單位。 –

+0

我的意思是說你的建議有效,我只需要添加導入。 – Jus12

3

沒有,則Unit返回類型是無關緊要的。

scala> @tailrec def f(i: Int) { if (i >= 0) { println(i); f(i - 1) } } 
f: (i: Int)Unit 

但是:

scala> @tailrec def f(i: Int) { if (i >= 0) { f(i - 1); println(".") } } 
<console>:11: error: could not optimize @tailrec annotated method f: 
    it contains a recursive call not in tail position 

你需要有遞歸調用的最後一次通話,返回類型並不重要。

你在問題中的代碼是好的,但問題的標題會誤導。

+0

同意。我編輯了標題。感謝您的反例。 – Jus12