Code to determine the lat element of a list, using pattern matching:
@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
}
}
I want to compile the code, I am getting "yelled" by the compiler:
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
If I remove the @tailrec annotation - the code compiles . How can I modify the code in order to 开发者_Python百科do the tail rec optimization ?
You got a typo their. Your method is called last_rec
and you are calling last
which is clearly undefined. So just rename it to last
. And by the way you should return Option[A]
instead of A
. That way you can return None
when nothing is found instead of throwing the ugly NoSuchElementException
.
After removing the typo and adding agilesteel's suggestion:
@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)
}
}
In this case I would do what agilesteel suggested.
However, if you really wanted to throw an exception (in another different use case), you could do it in a statically typed way:
@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)
}
}
where later you could:
last_rec(Nil) match {
case Right(s) => println("Got a value")
case Left(e) => println("Got an exception")
}
精彩评论