2012-09-19 50 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]