0

使用模式匹配确定列表的 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 注释 - 代码编译。如何修改代码以进行尾部记录优化?

4

3 回答 3

3

你有一个错字他们。您的方法被调用last_rec并且您正在调用last这显然是未定义的。所以只需将其重命名为last. 顺便说一句,您应该返回Option[A]而不是A. 这样一来,您就可以None在没有发现任何东西时返回,而不是扔掉丑陋的NoSuchElementException.

于 2011-09-10T10:07:11.700 回答
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)
 }
}
于 2011-09-10T10:10:20.543 回答
1

在这种情况下,我会按照敏捷钢的建议去做。

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

@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")
}
于 2011-09-10T11:01:49.760 回答