【问题标题】:OCaml: How Can I execute a program that uses Tail Recursion?OCaml:如何执行使用尾递归的程序?
【发布时间】:2017-07-12 19:33:25
【问题描述】:

我正在使用尾递归编写一个函数,但我不知道如何执行。 通常,我使用 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。

【问题讨论】:

  • 您的程序在我的机器上运行良好。请注意,使用尾递归函数不需要做任何特别的事情,它是编译器在适用时自动完成的优化。
  • 是的,它可以工作,但是当我执行一个带有 70000 的列表时,会显示错误
  • @JulianaSouza 生成长列表的代码可能不是尾递归的。
  • 您能告诉我们您是如何生成包含 70000 个元素的列表的吗?正如 Anton 所建议的,这可能是错误发生的地方。
  • @RichouHunter ,问题就在这里!谢谢!

标签: ocaml tail-recursion


【解决方案1】:

据我所知@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 所说,运行尾递归代码没有什么特别的。

【讨论】:

    【解决方案2】:

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

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

    由于堆栈溢出,这意味着某些东西不是尾递归的。您刚刚展示的代码很好,并且完全是尾递归的,因此实际上是其他一些代码引发了异常。不是你的rev

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-15
      • 2020-04-07
      • 2019-04-29
      • 2017-03-09
      • 1970-01-01
      相关资源
      最近更新 更多