Scala 中的尾递归和 return 语句
我正在考虑这里提出的问题之一(为什么Scala 是否需要递归函数的返回类型?)以及如何改进代码。
不管怎样,我在想这样的事情:
def simpledb_update(name: String, metadata: Map[String, String]) = {
def inner_update(attempt: int): Unit = {
try {
db(config("simpledb_db")) += (name, metadata)
return
} catch {
case e =>
if (attempt >= 6) {
AUlog(name + ": SimpleDB Failed")
return
}
}
inner_update(attempt+1)
}
inner_update(0)
}
或者
def simpledb_update(name: String, metadata: Map[String, String]) {
def inner_update(attempt: int): Unit = {
try {
db(config("simpledb_db")) += (name, metadata)
} catch {
//Do I need the pattern match, since I don't
// care what exception is thrown???
if (attempt >= 6) {
AUlog(name + ": SimpleDB Failed")
} else {
inner_update(attempt+1)
}
}
}
inner_update(0)
}
第二个实现仍然是尾递归的(是第一个???)。对于函数何时是尾递归以及何时不是尾递归,我仍然有点模糊。
I was thinking about one of the questions asked here (Why does Scala require a return type for recursive functions?) and how to improve the code.
Anyway, I was thinking something like this:
def simpledb_update(name: String, metadata: Map[String, String]) = {
def inner_update(attempt: int): Unit = {
try {
db(config("simpledb_db")) += (name, metadata)
return
} catch {
case e =>
if (attempt >= 6) {
AUlog(name + ": SimpleDB Failed")
return
}
}
inner_update(attempt+1)
}
inner_update(0)
}
Or
def simpledb_update(name: String, metadata: Map[String, String]) {
def inner_update(attempt: int): Unit = {
try {
db(config("simpledb_db")) += (name, metadata)
} catch {
//Do I need the pattern match, since I don't
// care what exception is thrown???
if (attempt >= 6) {
AUlog(name + ": SimpleDB Failed")
} else {
inner_update(attempt+1)
}
}
}
inner_update(0)
}
Is the second implementation still tail recursive (is the first???). I'm still a bit hazy on when a function is tail recursive, and when it's not.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,这两个示例仍然是尾递归的,您首先进行检查/处理,最后进行递归调用。
术语文件简明地说:尾递归(n):如果你还没有厌倦它,请参阅尾递归。
Yes, both examples are still tail-recursive, you're doing the checking/processing first, with the recursive call last.
The Jargon File put it succinctly: Tail Recursion (n): If you aren't sick of it already, see tail recursion.
在Scala中,可以给函数添加tailrecursive注解,然后编译器会检查是否可以对函数进行尾调用优化。
In Scala, you can add tailrecursive annotation to the function, and then the compiler will check whether or not it can do tail call optimisation on the function.
尾递归很容易理解 - 如果函数 F 的所有代码路径中的最后一个表达式只是一个函数调用,那么它就是尾递归。但 Scala 编译器优化是否是尾递归 - 取决于。 JVM 不执行 TCO 的事实意味着 scala 编译器发挥了魔力。
scalac 可能无法优化的原因与多态性有关。如果该 Function 可以在子类中被重写,scalac 就无法对其进行优化。
@Timo Rantalaiho,使用 tailrec 注释是验证是否可以完成 TCO 的最安全方法。
Tail recursion is simple to understand - if the last expression, from all code paths of a function F, is simply a function call then it is tail recursive. But is it tail-recursive for Scala compiler to optimize - depends. The fact that JVM doesn't do TCO means scala compiler does the magic.
And the reason scalac might fail to optimize has to do with polymorphism. If the Function can be overridden in a subclass, scalac cannot optimize it out.
@Timo Rantalaiho, using the tailrec annotation is the safest way to verify if TCO can be done.