因此,尾部递归意味着在体内使用一个递归调用的递归函数。此外,它是最外层的,这意味着递归调用不在语句内部,而是在递归调用的参数上进行递归。 例如(这里我正在使用OCaml),
递归:
let rec fact n =
if n=0 then 1
else n* fact (n-1);;
尾递归:
let fact n =
let rec helper (n,m)=
if n=0 then m
else helper(n-1,n*m)
in
helper(n,1);;
我不明白为什么尾递归比另一个要好?
关于OCamel的一些问题:我们是否必须担心缩进?因为当我在tryOCamel中尝试时似乎没有。
此外,我们可以为OCaml问题制作新标签吗? 请帮助
答案 0 :(得分:1)
尾部递归不会引起常规递归所涉及的堆栈深度问题。由于尾部递归直接将结果返回给父级,因此在进行下一个递归调用时,将丢弃堆栈帧。这允许更深的(无限)递归。递归调用中的每个内部步骤基本上都被新调用替换。
在您的示例中:
let rec fact n =
if n=0 then 1
else n * fact (n-1);;
每次调用迭代时,必须存储n * fact(n-1)
中的前n个;因此,在展开堆栈时可以使用(n * ...)。
您的第二个示例将n *当前结果(m)作为参数传递,并且在堆栈“展开”时不需要任何操作,因为最后的n * m计算返回了完整的答案。