函数式语言导致使用递归来解决许多问题,因此许多函数式语言执行尾部调用优化(TCO)。 TCO导致从另一个函数(或其本身,在这种情况下也称为“尾递归消除”,它是TCO的子集)对该函数的调用,作为该函数的最后一步,不需要新的堆栈框架,这减少了开销和内存使用。
Ruby显然从功能语言(lambda,诸如map之类的函数等)中“借用”了许多概念,这让我感到好奇:Ruby是否执行尾部调用优化?
最佳答案
不,Ruby不执行TCO。但是,它也不执行TCO。
Ruby语言规范未提及TCO。它并没有说您必须这样做,但也没有说您不能这样做。您就是不能依靠它。
这与Scheme不同,在Scheme中,语言规范要求所有实现都必须执行TCO。但是它也与Python不同,在Python中,Guido van Rossum在很多场合(几天前的最后一次)都明确指出Python实现不应执行TCO。
松本行弘(Yukihiro Matsumoto)对TCO表示同情,他只是不想强制所有实现都支持它。不幸的是,这意味着您不能依赖TCO,否则,您的代码将不再可移植到其他Ruby实现中。
因此,某些Ruby实现执行TCO,但大多数不执行。例如,YARV支持TCO,尽管(目前)您必须在源代码中明确取消注释一行并重新编译VM,才能激活TCO-在将来的版本中,实现证明后将默认启用稳定。 Parrot虚拟机本身支持TCO,因此Cardinal也可以轻松地支持它。 CLR对TCO有所支持,这意味着IronRuby和Ruby.NET可以做到这一点。鲁比尼乌斯也可以做到。
但是JRuby和XRuby不支持TCO,而且它们可能不支持TCO,除非JVM本身获得了对TCO的支持。问题是这样的:如果您想有一个快速的实现,以及与Java的快速无缝集成,那么您应该与Java堆栈兼容,并尽可能使用JVM的堆栈。您可以使用蹦床或显式的延续传递样式轻松实现TCO,但是您不再使用JVM堆栈,这意味着每次您要调用Java或从Java调用Ruby时,都必须执行某种转换,这很慢。因此,XRuby和JRuby选择了在TCO和延续性上进行速度和Java集成(基本上存在相同的问题)。
这适用于所有想要与某些本身不支持TCO的主机平台紧密集成的Ruby实现。例如,我猜MacRuby将有同样的问题。
关于ruby - Ruby是否执行尾部调用优化?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/824562/