2012-09-19 87 views
1

我試圖寫一個接受一個int n,返回運行從N到0評估期間堆棧溢出(循環遞歸?)。 OCaml的

這樣下來列表的功能是什麼,我有

let rec downFrom n = 
let m = n+1 in 
if m = 0 then                     
    []                       
else                        
    (m-1) :: downFrom (m - 1);; 

函數編譯好的,但是當我測試它與任何int它給我的錯誤 堆棧溢出在評估(循環遞歸?)。

我知道這是本地變量,但我不知道另一種方式來聲明它。謝謝!!!

回答

1

首先,real你的程序出錯了,就是你有一個無限循環。爲什麼,因爲你的歸納基數是0,但你總是停留在n!這是因爲你在遞歸m - 1這實在是n + 1 - 1

我很驚訝,爲什麼這編譯,因爲它不包括rec關鍵字,這是必要的遞歸函數。爲了避免在OCaml的棧溢出,你通常切換到tail recursive風格,比如如下:

let downFrom n = 
    let rec h n acc = 
    if n = 0 then List.rev acc else h (n-1) (n::acc) 
    in 
    h n [] 

有人建議如下編輯:

let downFrom n = 
    let rec h m acc = 
     if m > n then acc else h (m + 1) (m::acc) 
    in 
    h 0 []; 

這樣可以節省到List.rev通話, 我同意。

+0

謝謝!雖然我還沒有學習尾遞歸,但我將最後一條語句改爲(m-1):: downFrom(m-2),它的工作原理爲 – otchkcom

+2

作爲提示,我會(爲了更好的樣式)簡單地消除m的定義,隨處取代n + 1,否則看起來很尷尬。 –

+1

我修正了幾個拼寫錯誤,讓你的版本''downFrom'編譯。但是,它仍然會返回一個遞增的清單,而OP則要求遞減清單。 – jrouquie

1

遞歸的關鍵在於遞歸調用必須是問題的較小版本。您的遞歸調用不會創建較小版本的問題。它只是重複相同的問題。

0

您可以用過濾參數 語法嘗試:

let f = function 
    p1 -> expr1 
| p2 -> expr2 
| p3 -> ...;; 

let rec n_to_one =function 
    0->[] 
    |n->n::n_to_one (n-1);; 

# n_to_one 3;; 
- : int list = [3; 2; 1]