OCaml:我如何执行使用Tail Recursion的程序?

时间:2017-07-12 19:33:25

标签: ocaml tail-recursion

我正在使用Tail Recursion编写函数,但我不知道要执行。 通常,我使用 ocaml QuicksortTail.ml Qsort ,但是当我执行包含70000个元素的列表时会显示错误:

  

致命错误:异常Stack_overflow“

let rec trev l r = 
    match l with
        | [] -> r
        | x::xs -> trev xs (x::r);;
let rev l = trev l [];;

List.iter (fun x->print_int x) (rev[5;4;3;2;1])

我的oCaml是4.01。

2 个答案:

答案 0 :(得分:3)

@RichouHunter就我所见而言是正确的。

为了完整起见,这是一个顶级会话,显示您的代码正常工作:

$ rlwrap ocaml
        OCaml version 4.03.0

# let rec trev l r =
    match l with
        | [] -> r
        | x::xs -> trev xs (x::r);;
val trev : 'a list -> 'a list -> 'a list = <fun>
# let rev l = trev l [];;
val rev : 'a list -> 'a list = <fun>

# let rec range accum m n = if m > n then accum else range (n :: accum) m (n - 1);;
val range : int list -> int -> int -> int list = <fun>

# let big = range [] 1 70000;;
val big : int list =
  [1; 2; 3; ...]
# let revbig = rev big;;
val revbig : int list =
  [70000; 69999; 69998; ...]

正如@RichouHunter所说,运行尾递归代码没什么特别的。

答案 1 :(得分:3)

尾递归是一种特殊的递归,其中递归调用是函数中的最后一次调用。它不是一种执行模式,因此您不需要将任何特定标志传递给解释器或编译器以启用或禁用尾递归。它是程序的静态属性。

当一个调用处于尾部位置时(无论是否是一个递归调用并不重要),OCaml编译器将发出一个代码,它不会使用堆栈空间。翻译也是如此。调用不会消耗堆栈空间,因此您可以执行几乎无限数量的尾调用而不会导致堆栈溢出。

由于您正在获得堆栈溢出,这意味着某些东西不是尾递归的。您刚刚显示的代码很好,并且完美的尾递归,因此它是一些其他代码,实际上抛出异常。不是你的rev