为什么这不是尾递归

时间:2018-05-04 12:15:50

标签: recursion f# tail-recursion

我有一个(co?)递归函数对处理元组列表,并根据一些开始和结束标准将它们折叠成批。

我没有那么做f#所以我可能是愚蠢的。

我已经修改了一个简单的非尾递归版本,通过显式引入构成当前折叠状态的“tot”参数,我认为是尾递归的,但是我在大输入上得到了可怕的堆栈溢出....(在调试器和(调试).exe中)

可能有更好的方法将此作为明确的折叠......但这几乎不是重点,重点是为什么看起来不是尾递归?

    let rec ignoreUntil2 (xs : List<(string * string)>)  tot = //: List<(string * string)> -> List<List<(string * string)>> -> List<List<(string * string)>> = 
        match xs with              
        | [] -> tot
        | ((s1,s2)::tail) -> 
            if s2.StartsWith("Start importing record: Product") then
                takeUntil2 [] ((s1,s2)::tail) tot
            else
                ignoreUntil2 tail tot
and takeUntil2 acc xs tot = // : List<(string * string)> -> List<(string * string)> -> List<List<(string * string)>> -> List<List<(string * string)>> =
        match xs with
        | [] -> acc :: tot
        | ((s1,s2)::tail)   ->
            let newAcc = ((s1,s2)::acc)
            if s2.StartsWith("Finished importing record: Product") then
                ignoreUntil2 tail (newAcc :: tot)
            else
                takeUntil2 newAcc tail tot

1 个答案:

答案 0 :(得分:4)

您的代码尾递归。

  

(在调试器和(调试).exe中)

默认情况下,F#编译器不会在调试模式下消除尾调用。您需要显式启用--tailcalls选项或在发布模式下编译。