函数式语言导致使用递归来解决许多问题,因此许多函数式语言执行尾部调用优化(TCO).TCO导致从另一个函数(或自身,在这种情况下,此功能也称为尾部递归消除,它是TCO的子集)调用函数,作为该函数的最后一步,不需要新的堆栈帧,从而减少开销和内存使用.

Ruby显然"borrow "了函数语言(lambdas、map等函数)中的许多概念,这让我好奇:Ruby是否执行尾部调用优化?

推荐答案

不,Ruby不执行TCO.然而,它也不执行TCO.

Ruby语言规范没有提到TCO.它没有说你必须这么做,但也没有说你必须这么做.你就是不知道.

这与方案不同,方案中all实现must执行TCO的语言规范requires.但它也不同于Python,Guido van Rossum曾多次(上一次是几天前)明确表示Python实现should not执行TCO.

松本幸弘同情TCO,他只是不想强迫all个实现来支持它.不幸的是,这意味着您不能依赖TCO,否则,您的代码将无法移植到其他Ruby实现中.

因此,一些Ruby实现执行TCO,但大多数都不执行.例如,YARV支持TCO,尽管(目前)您必须显式取消源代码中的一行注释并重新编译VM,以激活TCO——在future 的版本中,在实现证明稳定后,它将默认启用.Parrot虚拟机本机支持TCO,因此Cardinal也可以很容易地支持它.CLR对TCO有一些支持,这意味着IronRuby和Ruby.NET可能会做到.鲁宾尼乌斯可能也能做到.

但是JRuby和XRuby不支持TCO,而且很可能不会,除非JVM本身获得了对TCO的支持.问题是:如果您想要快速实现,并与Java快速无缝集成,那么您应该与Java保持堆栈兼容,并尽可能多地使用JVM的堆栈.你可以很容易地用蹦床或显式的延续传递方式实现TCO,但是你不再使用JVM堆栈,这意味着每次你想调用Java或从Java调用Ruby时,你都必须执行某种转换,这是很慢的.因此,XRuby和JRuby Select 了速度和Java集成,而不是TCO和continuations(基本上都有相同的问题).

这适用于所有希望与不支持TCO的主机平台紧密集成的Ruby实现.例如,我猜MacRuby也会有同样的问题.

Ruby相关问答推荐

多线程期间的 MRI ruby​​ 内存访问特性

如何在 ruby​​ 中通过 SSL 调用 HTTP POST 方法?

方法如何在 Ruby 中使用哈希参数?

Coffeescript 中等效的 Ruby .times

如何在 ruby​​ 中编写负循环,例如 for(i=index; i >= 0; i --)

在 Ruby 中创建数字、字符串、数组或哈希的 md5 哈希

Ruby 中的排序稳定吗?

RSpec:如何测试文件操作和文件内容

从 Ruby 中的 DateTime 中减go n 小时

如何按字母顺序排列忽略大小写的数组?

rspec 是否有比 target.should < 6 更具体的东西?

获取类中声明的所有实例变量

确定一个值是否存在于哈希数组中

Ruby CSV - 获取当前行/行号

为什么 Ruby 没有真正的 StringBuffer 或 StringIO?

如何使用密码保护我的 /sidekiq 路由(即需要对 Sidekiq::Web 工具进行身份验证)?

map、each 和 collect 有什么区别?

何时在 Ruby 中使用 `require`、`load` 或 `autoload`?

不能在windows上安装thin

相当于 Ruby 的 cURL?