函数式语言导致使用递归来解决很多问题,因此许多语言执行尾调用优化(TCO)。 TCO 导致从另一个函数(或本身,在这种情况下,此功能也称为尾递归消除,它是 TCO 的子集)调用函数,作为该函数的最后一步,不需要新的堆栈帧,这减少了开销和内存使用。
Ruby 显然从函数式语言中“借用”了许多概念(lambda、map 等函数等),这让我很好奇:Ruby 是否执行尾调用优化?
不,Ruby 不执行 TCO。然而,它也并不not执行 TCO。
Ruby 语言规范没有提及任何有关 TCO 的内容。它没有说你必须这样做,但也没有说你can't做吧。你就是不能rely on it.
这与Scheme不同,Scheme中语言规范requires that all实施must执行 TCO。但它也与 Python 不同,Guido van Rossum 在多个场合(最后一次是在几天前)非常明确地表示,Python 实现不应该执行 TCO。
松本幸弘同情TCO,他只是不想强迫all支持它的实现。不幸的是,这意味着您不能依赖 TCO,或者如果您这样做,您的代码将不再可移植到其他 Ruby 实现。
因此,一些 Ruby 实现执行 TCO,但大多数不执行。例如,YARV 支持 TCO,尽管(目前)您必须显式取消源代码中的一行并重新编译 VM,才能激活 TCO – 在未来版本中,在实现证明之后,它将默认启用稳定的。 Parrot 虚拟机本身支持 TCO,因此 Cardinal 也可以很容易地支持它。 CLR 对 TCO 有一定的支持,这意味着 IronRuby 和 Ruby.NET 可能可以做到这一点。鲁比尼乌斯或许也能做到。
但 JRuby 和 XRuby 不支持 TCO,而且很可能不会,除非 JVM 本身获得对 TCO 的支持。问题是这样的:如果你想要快速实现,并且与Java快速无缝集成,那么你应该与Java堆栈兼容,并尽可能使用JVM的堆栈。您可以很容易地使用 Trampolines 或显式连续传递风格实现 TCO,但是您不再使用 JVM 堆栈,这意味着每次您想要调用 Java 或从 Java 调用 Ruby 时,您都必须执行某种操作转换,速度很慢。因此,XRuby 和 JRuby 选择了速度和 Java 集成,而不是 TCO 和延续(基本上有相同的问题)。
这适用于想要与某些本身不支持 TCO 的主机平台紧密集成的所有 Ruby 实现。例如,我猜 MacRuby 也会有同样的问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)