Groovy 的尾递归
我编写了 3 个阶乘算法:
- 我预计会因堆栈溢出而失败。没问题。
- 我尝试尾递归调用,并将以前的算法从递归转换为迭代。它不起作用,但我不明白为什么。
- 我使用 Trampoline() 方法,它按我的预期工作得很好。
def factorial
factorial = { BigInteger n ->
if (n == 1) return 1
n * factorial(n - 1)
}
factorial(1000) // stack overflow
factorial = { Integer n, BigInteger acc = 1 ->
if (n == 1) return acc
factorial(n - 1, n * acc)
}
factorial(1000) // stack overflow, why?
factorial = { Integer n, BigInteger acc = 1 ->
if (n == 1) return acc
factorial.trampoline(n - 1, n * acc)
}.trampoline()
factorial(1000) // It works.
I coded 3 factorial algorithms:
- I expect to fail by stack overflow. No problem.
- I try a tail recursive call, and convert the previous algorithm from recursive to iterative. It doesn't work, but I don't understand why.
- I use
trampoline()
method and it works fine as I expect.
def factorial
factorial = { BigInteger n ->
if (n == 1) return 1
n * factorial(n - 1)
}
factorial(1000) // stack overflow
factorial = { Integer n, BigInteger acc = 1 ->
if (n == 1) return acc
factorial(n - 1, n * acc)
}
factorial(1000) // stack overflow, why?
factorial = { Integer n, BigInteger acc = 1 ->
if (n == 1) return acc
factorial.trampoline(n - 1, n * acc)
}.trampoline()
factorial(1000) // It works.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
从版本 2.3 开始,Groovy 通过方法的 @TailRecursive 注释支持尾递归:
http://java.dzone.com/articles/groovy-goodness-more-efficient
Starting with version 2.3 Groovy supports tail recursion with the @TailRecursive annotation for methods:
http://java.dzone.com/articles/groovy-goodness-more-efficient
Java 中没有尾递归,因此 Groovy 中也没有尾递归(不使用 就像你所展示的trampoline()
)我见过的最接近的是一个巧妙包装的 AST 转换 while 循环中的返回递归编辑
你是对的,Java(以及 Groovy)确实支持这种尾部调用迭代,但是,它似乎并不支持使用闭包...
但是此代码(使用方法而不是用于
fact
调用的闭包):当保存为
Test.groovy
并使用执行时groovy Test.groovy
运行,并打印答案:作为猜测,我想说 JVM 不知道如何优化闭包(就像它对方法一样),因此这个尾部调用不会在执行之前的字节码
There is no tail recursion in Java, and hence there is none in Groovy either (without using something liketrampoline()
as you have shown)The closest I have seen to this, is an AST transformation which cleverly wraps the return recursion into a while loopEdit
You're right, Java (and hence Groovy) do support this sort of tail-call iteration, however, it doesn't seem to work with Closures...
This code however (using a method rather than a closure for the
fact
call):When saved as
Test.groovy
and executed withgroovy Test.groovy
runs, and prints the answer:As a guess, I would say that the JVM does not know how to optimise closures (like it does with methods), so this tail call does not get optimised out in the bytecode before it is executed