1. ホーム
  2. scala

[解決済み] 末尾再帰関数が最適化されるためのScalaアノテーションは何ですか?

2022-10-18 20:33:29

質問

私は @tailrec アノテーションがあり、コンパイラが末尾再帰関数を最適化することを保証します。それを宣言の前に置くだけですか?Scalaをスクリプトモードで使う場合にも有効でしょうか(例えば :load <file> を使用する場合)にも有効ですか?

どのように解決するのですか?

から、" テールコール、@tailrec、トランポリン "ブログの記事です。

  • Scala 2.8では、新しい @tailrec アノテーションを使用して、どのメソッドが最適化されているかという情報を得ることができます。

    このアノテーションにより、コンパイラが最適化することを望む特定のメソッドをマークすることができます。

    もし、コンパイラが最適化しない場合は、警告が表示されます。
  • Scala 2.7 以前では、メソッドが最適化されているかどうかを調べるには、手動テストまたはバイトコードの検査に頼る必要があります。

を追加すると @tailrec アノテーションを追加して、変更がうまくいったかどうかを確認することができます。

import scala.annotation.tailrec

class Factorial2 {
  def factorial(n: Int): Int = {
    @tailrec def factorialAcc(acc: Int, n: Int): Int = {
      if (n <= 1) acc
      else factorialAcc(n * acc, n - 1)
    }
    factorialAcc(1, n)
  }
}


そしてそれはREPLから動作します(例として Scala REPL のヒントとコツ ):

C:\Prog\Scala\tests>scala
Welcome to Scala version 2.8.0.RC5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_18).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.annotation.tailrec
import scala.annotation.tailrec

scala> class Tails {
     | @tailrec def boom(x: Int): Int = {
     | if (x == 0) throw new Exception("boom!")
     | else boom(x-1)+ 1
     | }
     | @tailrec def bang(x: Int): Int = {
     | if (x == 0) throw new Exception("bang!")
     | else bang(x-1)
     | }
     | }
<console>:9: error: could not optimize @tailrec annotated method: it contains a recursive call not in tail position
       @tailrec def boom(x: Int): Int = {
                    ^
<console>:13: error: could not optimize @tailrec annotated method: it is neither private nor final so can be overridden
       @tailrec def bang(x: Int): Int = {
                    ^