我读过 JAVA 8 支持 Tail 调用优化,但我想我一定没有正确实现它。
那你就读错了。或者,您阅读了正确的陈述,但没有正确解释它。
Java,这种语言,不支持尾调用递归。从来没有。它可能永远不会*。
然而,java(VM)有一些功能使其他非 java 语言更容易编译成类文件以在 java 运行时上运行,以支持 TCO。这大概就是您读到的内容。
我只是在寻找有关如何使用真正的尾部调用优化、lambda 表达式或其他任何方式的建议。
用 scala 或类似的语言编写它。
说真的,java怎么没有TCO???
TCO 成本高昂:Java 有一条规则,即当发生错误时,您将获得堆栈跟踪,而堆栈跟踪是一个定义明确的概念,最重要的是,它为每个逻辑调用跟踪 1 个堆栈帧。这cannot如果存在 TCO,则继续。当然,还有一些选择:堆栈上的每个单独帧都可以获得一个“计数器”,以便堆栈跟踪保持较小的内存占用量,同时正确表示“并且该调用序列已重复出现 8190581 次”。语言规范中还有大量关于它如何工作、何时启动和不启动以及这一切意味着什么的文本,并且规范中的任何其他页面都是永远的维护负担 - 这不是“它”的情况绝对优于向 java 添加 TCO,因此当我们开始使用它时,灌篮高手,任何具有该功能的 Pull 请求都将立即集成”。
此外,TCO 作为一种模型是一种做事方式,但不是唯一的方式。对于任何可以编写为 TCO 递归应用程序的东西,将其重构为基于循环的非递归算法通常并不是那么困难。与基于收益的异步操作相比,您当然可以重写(嘿,这都是图灵机),但重写会很困难,并且生成的代码相当难以理解。我不想讨论产量/异步风格编码的价值(或缺乏价值),只是指出 TCO 没有那种“啊,但是,ifTCO 是个好主意,那么只有 TCO 才行”。
我没有现成的链接,但是那些对 Java 的未来有相当大影响力的人(例如 Brian Goetz、Mark Reinhold 等)已经说过类似的言论。如果您真的致力于尝试将其添加到 java 中,我建议您在网络上搜索这些陈述,然后尝试专门形成一些论据来解决它们所陈述的问题。因为如果你不能说服那些人,这永远不会发生。
那么我在java中做什么呢?
不要使用递归;使用while
or for
反而。
更新:那篇博客文章怎么样?
在您链接到的评论中这个博客条目。那是..不是TCO。
这就是使用 lambda 编写一个框架,让您或多或少地模拟 TCO,但它不是 TCO。该博客描述了一个小框架 - 因此,您需要他们粘贴的所有内容:特别是 TailCall 接口。
该代码的工作原理如下:
- 您的“递归”方法根本不是递归的,它总是快速返回而不调用自身。
- 不过,它返回一个可以调用自身的 lambda。但是,正如我们刚刚介绍的,调用自己可以快速返回而无需递归,并且它返回一个函数。
- 框架将执行您的函数,该函数通常会生成一个函数(或实际结果)。它循环(所以没有递归),重复应用以下过程:“调用函数。如果它返回一个函数,则循环。如果它返回一个结果,好吧,这就是我们想要的结果,所以只需返回它”。
这描述了 TCO 试图完成的任务(使用不同的参数一遍又一遍地重复调用相同的函数,直到达到硬编码的边缘情况,然后反向退出),但不使用 TCO 来完成它。
因此,那篇博客文章说“看,Java 中的 TCO!”具有误导性。
就像我说的:“看,隧道墙上的画笔!”并描述如何使用cans喷漆以这样的方式涂漆隧道壁looks就像是用手刷过的一样。这很好,但称其为“刷墙”是有误导性的。充其量你可以说:“想要在隧道中制作画笔风格的艺术?好吧,你不能,我也无法解决这个问题,但我可以告诉你如何获得类似的结果!”。
*)永远不要说永远不会,但我的意思是:目前还没有任何计划,并且 Java 平台的未来计划要持续很多年,并且是相当公开的。我对“java(语言)在 4 年内没有尾调用递归”有 1 到 40 的赔率,并且仍然接受这个赌注。