开发者

Tail recursion and return statement in Scala

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]) {

  d开发者_开发知识库ef 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.


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜