Algorithm 这个实现是递归的吗

Algorithm 这个实现是递归的吗,algorithm,ocaml,tail-recursion,Algorithm,Ocaml,Tail Recursion,我在一本算法书中读到Ackermann函数不能进行尾部递归(他们说“它不能转换为迭代”)。我对此很困惑,所以我试着想出了这个: let Ackb m n = let rec rAck cont m n = match (m, n) with | 0, n -> cont (n+1) | m, 0 -> rAck cont (m-1) 1 | m, n -> rAck (fun x -> rAck cont (m-1) x)

我在一本算法书中读到Ackermann函数不能进行尾部递归(他们说“它不能转换为迭代”)。我对此很困惑,所以我试着想出了这个:

let Ackb m n =
  let rec rAck cont m n = 
    match (m, n) with
      | 0, n -> cont (n+1)
      | m, 0 -> rAck cont (m-1) 1
      | m, n -> rAck (fun x -> rAck cont (m-1) x) m (n-1)
  in rAck (fun x -> x) m n
;;
(这是OCaml/F代码)

我的问题是,我不确定这是否真的是尾部递归。你能确认一下吗?若否,原因为何?最后,当人们说Ackermann函数不是原始递归函数时,这意味着什么


谢谢

是的,它是尾部递归的。每个函数都可以通过显式转换为tail rec

这并不意味着函数将在恒定内存中执行:您构建了必须分配的连续堆栈。将该数据表示为简单的代数数据类型可能更有效

存在是一个非常不同的概念,与数学理论中使用的某种形式的递归定义的表达能力有关,但可能与你所知道的计算机科学不太相关:它们的表达能力非常低,并且系统具有功能组合(从Gödel的系统T开始),像所有当前的编程语言一样,它的功能要强大得多

就计算机语言而言,基本递归函数大致相当于没有一般递归的程序,其中所有循环/迭代都是静态有界的(可能的重复次数是已知的)。

是。

根据定义,任何递归函数都可以转换为迭代,只要它可以访问无界堆栈式构造。有趣的问题是,它是否可以在没有堆栈或任何其他无界数据存储的情况下完成


只有当尾部递归函数的参数大小有界时,它才能转化为这样的迭代。在您的示例(以及几乎所有使用continuations的递归函数)中,
cont
参数是一个可以扩展到任何大小的堆栈。事实上,延续传递样式的整个要点是将通常出现在调用堆栈上的数据(“返回后该怎么办?”)存储在延续参数中。

在传递lambda时,您仍然在构建函数调用的“堆栈”。是的,它是尾部递归的。您可以使用ocamlopt和
-dlinear
选项编译文件。这将有助于您确定函数是否使用尾部调用。我认为,关于基本递归性,这里需要注意的重要一点是,基本递归函数可以在常量空间中实现(假设您要计算的数字可以存储在常量空间中),而Ackermann函数不能。这是什么“按定义”是指这里?你在这里使用什么“递归函数”的定义?