2010-11-01 63 views
1

我想實現一個memoized斐波那契數字函數,我遇到了一個編譯錯誤,我不能理清。以下代碼是我迄今爲止的內容。斯卡拉遞歸關閉編譯錯誤

var fibs = Map.empty[Int, Int] 
fibs += 0 -> 1 
fibs += 1 -> 1 
fibs += 2 -> 2 
val fib = (n: Int) => { 
    if (fibs.contains(n)) return fibs.apply(n) 
    else{ 
    // Error here 
    val result = fib(n - 1) + fib(n - 2) 
    fibs+= n -> result 
    return result 
    } 
} 
println(fib(100)) 

的錯誤是:

遞歸fib需要鍵入

我試圖進入返回類型在不同的地方封閉,但我似乎無法得到它上班。

聲明封閉像val fib = (n: Int): Int => {會產生不同的編譯錯誤。

你能幫我解決這個編譯錯誤嗎?

回答

3

您必須顯式設置遞歸函數的返回類型。它不能推斷出類型,因爲推理是循環的。 So:def fib (n: Int): Int = ...

+0

聲明等'VAL FIB =封閉件(N:智力):INT => {'產生不同的編譯錯誤。 – jjnguy 2010-11-01 03:50:35

+0

另外,感謝您的意見。 – jjnguy 2010-11-01 03:51:38

+2

我給你了'def'語法。如果你想使用'val'來定義函數,你必須像通常那樣給它一個類型:'val fib:(Int => Int)=(n:Int)=> {...}' – 2010-11-01 03:55:26

5

您可以定義Ben Jackson建議的方法(即def fib (n: Int): Int = ...)。

函數值不能遞歸。 編輯:原來they can be recursive;你只需要幫助更多的類型推理。此外,你需要擺脫return;它只能在方法中使用。

以下工作:

var fibs = Map.empty[Int, Int] 
fibs += 0 -> 1 
fibs += 1 -> 1 
fibs += 2 -> 2 
val fib: (Int => Int) = n => { 
    if(fibs contains n) 
    fibs(n) 
    else { 
    val result = fib(n - 1) + fib(n - 2) 
    fibs += n -> result 
    result 
    } 
} 
println(fib(100)) 

你也應該在this blogpost看一看,瞭解你怎麼能抽象掉了記憶化與lambda表達式的幫助邏輯。

+0

另見http://stackoverflow.com/questions/3640823/in-scala-2-8-what-type-to-use-to-store-an-in-memory-mutable-data-table – 2010-11-01 05:27:36

+0

感謝您的更新。 – jjnguy 2010-11-01 14:10:51

1

擺脫return的,因爲它們只能def,不val使用,並宣佈fib的類型,因爲這是遞歸定義Scala的要求。

val fib: (Int => Int) = (n: Int) => { 
    if (fibs.contains(n)) fibs.apply(n) 
    else{ 
    val result = fib(n - 1) + fib(n - 2) 
    fibs+= n -> result 
    result 
    } 
} 

注意fib(100)將溢出的Int

+0

這聽起來正是我所需要的,謝謝。 – jjnguy 2010-11-01 14:01:54