问题标签 [tail-call-optimization]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
4 回答
3582 浏览

java - 为什么这个递归斐波那契函数运行得这么差?

如果我运行以下代码:

我得到以下输出:

1134903170 递归版本耗时 5803 毫秒。1134903170 迭代版本耗时 0 毫秒。

我觉得我在这里做错了什么。我认为尾调用(递归斐波那契方法中的最后一行)将由编译器优化,使其在速度上更接近迭代版本。有谁知道为什么运行如此缓慢?它只是一个写得不好的函数吗?

注意我使用的是 Oracle JDK 1.7

0 投票
2 回答
334 浏览

f# - 尾递归函数的 System.OutOfMemoryException

我已将有问题的代码隔离到此函数(使用 ASP.NET 的 Membership 类):

我得到System.OutOfMemoryException了. 但我系统的内存消耗仅为. (我有一台非常强大的 16 GB 机器。)5626h120 percent

为什么上面的函数会溢出堆栈?不是递归写成tail吗?

在此先感谢您的帮助。

0 投票
2 回答
385 浏览

return - 为什么 return/redo 在调用上下文中评估结果函数,但不评估块结果?

return昨晚我从函数中了解到 /redo 选项。它允许您返回另一个函数,然后在调用站点调用该函数并从同一位置重新调用评估器

尽管它foo是一个只接受一个参数的函数,但它现在的行为就像一个接受两个参数的函数。否则,类似的事情将要求调用者知道您正在返回一个函数,并且该调用者必须手动对其使用do评估器。

因此,如果没有return/redo,您将得到:

foo消耗它的一个参数并按值返回一个函数(没有调用它,因此解释器继续前进)。然后表达式评估为 10。如果return/redo不存在,您必须编写:

这使调用者不必知道(或关心)您是否选择返回要执行的函数。并且很酷,因为您可以执行尾调用优化或为返回功能本身编写包装器之类的事情。这是return打印消息但仍退出函数并提供结果的变体:

但函数并不是唯一在do. 因此,如果这是“在呼叫站点消除对 DO 的需要”的一般模式,那么为什么不打印任何内容呢?

它只是按值返回块,就像正常返回一样。它不应该打印出“测试”吗?这就是do......呃,用它来做:

0 投票
1 回答
1039 浏览

prolog - 如何找出 Prolog 是否执行尾调用优化

使用 SWI Prolog(Win x64)的开发版本,我为确定性词法分析器(托管在 github)编写了 DCG 谓词(因此所有外部谓词都没有选择点):

现在使用(;)->很多,我想知道 SWI-Prolog 是否可以read_token(parser(Grammar, Tables), NewState, Token)使用 Tail-Call-Optimization 优化递归,或者我是否必须手动将谓词拆分为几个子句。我只是不知道如何找出解释器的作用,尤其是知道在运行调试器时 TCO 被禁用。

0 投票
2 回答
1298 浏览

scala - 为什么scala不进行尾调用优化?

只是玩延续。目标是创建一个函数,它将接收另一个函数作为参数,以及执行量 - 和返回函数,它将应用参数给定数量的时间。

实现看起来很明显

但没有问题 - 此代码因 StackOverflow 错误而失败。为什么这里没有尾调用优化?

我正在使用 Scala 插件在 Eclipse 中运行它,它在 Task_Mult$$anonfun$1.apply(Task_Mult.scala: 25) 在 Task_Mult$$anonfun$n_times_cont$1$1.apply(Task_Mult.scala:18)

ps

F# 代码,几乎是直接翻译,没有任何问题

0 投票
2 回答
453 浏览

c++ - Tail call optimization besides tail recursion?

Are there any tail call optimizations possible besides tail recursion? I've been trying to find or think of one that doesn't involve recursion, but with no success. Is it possible? Any examples?

0 投票
2 回答
756 浏览

c++ - 使用递归在恒定空间和线性时间中向后打印链表

在我看来,应该可以使用递归和尾调用优化在恒定空间和线性时间中向后打印循环链表。但是,由于在进行递归调用后尝试打印当前元素,我遇到了困难。通过检查反汇编,我看到该函数正在被调用而不是跳转到。如果我将其更改为向前打印而不是向后打印,则函数调用将被正确消除。

我已经看到了这个相关的问题,但是我对使用递归和 TCO 解决它特别感兴趣。

我正在使用的代码:

并编译

更新:使用 Joni 的答案解决了对循环列表的轻微修改

0 投票
2 回答
1272 浏览

lisp - 如何检测可以应用尾调用优化的函数?

我正在尝试编写一个 Scheme 解释器,但发现 TCO 难以实现。我不确定函数必须具备哪些属性才能使 TCO 发挥作用。

1) 在定义结尾处带有自递归调用的函数:

2) 具有不在定义末尾的自递归调用的函数:

3) 在返回之前将递归调用存储在变量中的函数:

4) 相互递归函数:

5) 在函数定义的末尾简单地调用另一个不相关的函数:

6)我能想到的最棘手的情况是闭包。如果我坚持对范围内变量的引用怎么办?

7) 在函数定义的末尾调用另一个函数,以自递归调用作为参数:

据我了解,TCO 实现(在 Scheme 和 Common Lisp 中)重写了对 TCO 友好的函数,因此它们必须能够静态检测对 TCO 友好的函数。

我想知道的是:

  • TCO 会重写哪些函数,为什么只重写这些函数?
  • 是否发生 TCO 重写但函数仍线性消耗内存的情况(例如 7)?
0 投票
0 回答
167 浏览

c++ - 递归函数模板中的运行时尾调用优化

一些库从模板生成控制流结构,例如“安全switch”或访问者模式的表调度。

有没有人测量过此类结构的堆栈内存使用情况或发布了有关它们与尾调用优化的交互或一般可行性的任何信息?

我正在考虑一种运行时递归策略,即从模板生成循环。如果它不能依赖尾调用优化,它将不可避免地溢出堆栈。

0 投票
2 回答
366 浏览

scala - 如何在使用延续传递风格遍历树状结构时实现尾调用优化

我尝试使用中的连续传递样式实现尾调用优化以遍历树线结构。不幸的是,我以前使用的经验并没有多大帮助。我有没有尾优化的递归调用:

之后我尝试使用@annotation.tailrecand重写TailCalls,但仍然不确定如何装饰延续

提前致谢

ps:关于要点的完整示例