当前位置: 首页 > 知识库问答 >
问题:

为什么这不是尾部递归

壤驷坚
2023-03-14

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

我做得不多,所以我可能很愚蠢。

我已经修改了一个简单的非尾部递归版本,通过明确引入一个“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个答案

白博赡
2023-03-14

您的代码是尾部递归的。

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

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

 类似资料:
  • 我试图编写一个函数repeat(s:String,n:Int),它将串接字符串s n次并返回它,但由于某种原因,我没有得到正确的结果,并且得到了一个错误,即它不是尾部递归的,我在逻辑上很难理解为什么它不是尾部递归的。 在连接完成之前,是否必须处理递归?我该如何解决这个问题?使递归重复(s,n-1)不起作用,因为它会递归s太多次,但我不确定还有什么其他方法可以做到。 ps:我这么做主要是为了练习递归

  • 我想我理解了教科书中对尾部递归函数的定义:在函数调用后不执行任何计算的函数。我还发现,作为一个结果,尾部递归函数的内存效率会更高,因为它每次调用只需要一条记录,而不是每次都需要保留一条记录(就像在普通递归中那样)。 我不太清楚的是,这个定义如何应用于嵌套调用。我将提供一个例子: 我最初给出的答案是,根据定义,它不是尾部递归的(因为外部调用是在计算内部调用之后执行的,所以其他计算是在第一次调用之后完

  • 如果我运行deldeldel(“adel”),它会返回一个,但是,adel的长度是4,这意味着最后一个字符串索引是3,为什么str.substring(4,str.length()没有超出范围?

  • 我有两个gcd函数的实现: 函数gcd1是尾递归的,而gcd2使用的是时循环。 我已经验证了rubinius通过对阶乘函数进行基准测试来实现TCO,只有通过阶乘函数,基准测试才表明递归版本和迭代版本是“相同的ish”(我使用了基准测试IP)。 但对于上述情况,基准测试表明,gcd1比gcd2快至少两倍(递归比迭代快两倍,甚至更快)。 我用来基准测试的代码是这样的: 结果: 我正在运行Arch li

  • 我有一个关于如何将“递归”转换为“尾部递归”的问题。 这不是家庭作业,只是在我试图润色算法书籍中的递归定理时出现的一个问题。 我熟悉使用递归的两个典型示例(阶乘和斐波那契序列),也知道如何以递归方式和尾部递归方式实现它们。 我的代码如下(我使用Perl只是为了使其简单,但可以轻松地转换为C/Java/C)。 运行代码时,输出如下: 递归函数在返回之前使用不同的参数调用自己两次。我尝试了几种方法将其

  • 问题内容: 对于Java的处理方式以及涉及到的数字和其他类型的数字,我有些困惑。例如: 输出(也许您应该先猜测一下): 这不能编译是可以预料的,是不同的对象。 令我有些惊讶的是,默认情况下9是an ,并且1)甚至没有编译。请注意,您不能将放入期望使用的方法中,但是在这里它们是相等的。 由于两个相同的原因,这令人惊讶,但似乎更糟。 不足为奇,因为自动装箱到和。 不足为奇,因为不同类中的对象不应该是。