Как я могу преобразовать эту функцию Scala для оптимизации - PullRequest
0 голосов
/ 10 сентября 2011

Код для определения элемента 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 ]

3 голосов
/ 10 сентября 2011

Опечатка их. Ваш метод называется last_rec, а вы вызываете last, который явно не определен. Так что просто переименуйте его в last. И, кстати, вы должны вернуть Option[A] вместо A. Таким образом, вы можете вернуть None, когда ничего не найдено, вместо того, чтобы выбросить уродливое NoSuchElementException.

1 голос
/ 10 сентября 2011

В этом случае я бы сделал то, что предложил 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")
}
1 голос
/ 10 сентября 2011

После удаления опечатки и добавления предложения 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)
 }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...