如何转换此scala函数以进行优化

时间:2011-09-10 09:56:43

标签: scala tail-recursion tail-call-optimization

使用模式匹配确定列表的lat元素的代码:

  @tailrec
  def last_rec[A](list : List[A]) : A = {
    list match {
      case (x :: Nil) => x
      case (_ :: xs) => last_rec(xs)
      case Nil => throw new NoSuchElementException
    }
  }

我想编译代码,我正在被编译器“大喊”:

PS D:\workspace\scala\P99> scalac .\P01.scala
.\P01.scala:18: error: could not optimize @tailrec annotated method last2: it contains a recursive call not in tail position
      case Nil => throw new NoSuchElementException
                        ^
one error found

如果我删除@tailrec注释 - 代码编译。如何修改代码以进行尾部优化?

3 个答案:

答案 0 :(得分:3)

你得到了一个错字。您的方法称为last_rec,您正在调用last,这显然是未定义的。所以只需将其重命名为last即可。顺便说一下,您应该返回Option[A]而不是A。这样,您可以在找不到任何内容时返回None,而不是抛出丑陋的NoSuchElementException

答案 1 :(得分:1)

删除拼写错误并添加agilesteel的建议后:

@tailrec
def last_rec[A](list : List[A]) : Option[A] = {
  list match {
   case (x :: Nil) => Some(x)     
   case Nil => None
   case (_ :: xs) => last_rec(xs)
 }
}

答案 2 :(得分:1)

在这种情况下,我会做agilesteel所建议的。

但是,如果你真的想抛出异常(在另一个不同的用例中),你可以用静态类型的方式来做:

@tailrec
  def last_rec[A](list : List[A]) : Either[NoSuchElementException,A] = {
    list match {
      case (x :: Nil) => Right(x)
      case (_ :: xs) => last_rec(xs)
      case Nil => Left(new NoSuchElementException)
    }
  }

以后你可以:

last_rec(Nil) match {
 case Right(s) => println("Got a value")
 case Left(e) => println("Got an exception")
}