Functional programming 将尾部递归转换为非尾部递归

Functional programming 将尾部递归转换为非尾部递归,functional-programming,Functional Programming,我想知道是否有任何方法可以将尾部递归函数转换为非尾部递归函数。我知道,如果关注效率,尾部递归函数比没有尾部递归函数好,但在验证中,尾部递归并不合适 谢谢,我怀疑这个问题是否恰当,因为尾部递归消除是一种优化,如果需要,为了验证的目的,您可以忽略或关闭它。我猜用跳转替换调用可能会混淆它或损坏某些安全属性 但是,如果您确实想这样做,则需要更改源代码,以便递归函数调用不再处于尾部位置。棘手的部分将是确保优化程序不会再次更改您的代码 考虑这个F尾递归阶乘函数: let rec fact n v =

我想知道是否有任何方法可以将尾部递归函数转换为非尾部递归函数。我知道,如果关注效率,尾部递归函数比没有尾部递归函数好,但在验证中,尾部递归并不合适


谢谢,

我怀疑这个问题是否恰当,因为尾部递归消除是一种优化,如果需要,为了验证的目的,您可以忽略或关闭它。我猜用跳转替换调用可能会混淆它或损坏某些安全属性

但是,如果您确实想这样做,则需要更改源代码,以便递归函数调用不再处于尾部位置。棘手的部分将是确保优化程序不会再次更改您的代码

考虑这个F尾递归阶乘函数:

let rec fact n v =
    if n <= 1
        then v
        else fact (n-1) (n*v)
现在我们可以更改尾部调用,实际上:


类似的技巧也适用于其他语言。

为什么尾部递归不适合验证?您的意思是从使用累加器参数转换的尾部递归函数恢复原始递归函数吗?i、 摆脱这个累加器参数,这就是你想要的吗???将尾部递归函数转换成非尾部递归函数似乎是一个很好的挑战,原因有很多。例如,在逆向工程中,人们可能有兴趣以更清晰、更合适的形式恢复功能;正如您所知,无尾递归函数比其尾部递归形式更容易理解。此外,如果您想通过归纳证明此属性,例如:factorialn=factorialTerminalen,0使用任何定理证明器,您将不会成功,因为初始值为0。这就是为什么我说尾部递归函数不适合验证的原因。我对程序效率一点也不感兴趣。从尾部递归到递归的转换是不可行的。尾部递归已经是递归了。故事结束了。为了便于理解,YMMV。我的也可以所以除非你给我们举个例子,完整的代码和所有的东西,否则你的答案是不清楚的。我对程序优化不感兴趣。尾部递归程序有时很难理解,例如在逆向工程中,我必须能够以更合适的形式恢复初始的非尾部递归程序。有些算法自然是尾部递归的,因此,尾部递归版本也可能是最简单的形式。无论什么原因,我们都必须能够进行这种转换。我的答案将适用于所有情况。好的,假设你做了相反的方向,将非尾部递归函数f转换为尾部递归函数g。你怎么能证明g是正确的?
// we'll never set this to true, but the compiler doesn't know this
let mutable actuallyDoSomething = false
let doNothing() =
    if actuallyDoSomething then failwith "Don't set actuallyDoSomething!"
let rec fact n v =
    if n <= 1
        then v
        else
            let res = fact (n-1) (n*v)
            doNothing()
            res