函数式语言导致使用递归来解决许多问题,因此许多函数式语言执行尾部调用优化(TCO).TCO导致从另一个函数(或自身,在这种情况下,此功能也称为尾部递归消除,它是TCO的子集)调用函数,作为该函数的最后一步,不需要新的堆栈帧,从而减少开销和内存使用.
Ruby显然"borrow "了函数语言(lambdas、map等函数)中的许多概念,这让我好奇:Ruby是否执行尾部调用优化?
函数式语言导致使用递归来解决许多问题,因此许多函数式语言执行尾部调用优化(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也会有同样的问题.