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]) : 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 に答える
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 に答える