Qual é a anotação Scala para garantir que uma function recursiva final seja otimizada?

Eu acho que existe @tailrec anotação @tailrec para garantir que o compilador otimize uma function recursiva @tailrec . Você acabou de colocar na frente da declaração? Isso também funciona se o Scala for usado no modo de script (por exemplo, usando :load sob REPL)?

    Na postagem do blog ” Chamadas de cauda, ​​@tailrec e trampolins “:

    • No Scala 2.8, você também poderá usar a nova anotação @tailrec para obter informações sobre quais methods são otimizados.
      Esta anotação permite marcar methods específicos que você espera que o compilador otimize.
      Você receberá um aviso se eles não forem otimizados pelo compilador.
    • No Scala 2.7 ou anterior, você precisará confiar no teste manual ou na inspeção do bytecode para descobrir se um método foi otimizado.

    Exemplo:

    você pode adicionar uma anotação @tailrec para ter certeza de que suas alterações funcionaram.

     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) } } 

    E funciona a partir do REPL (exemplo das dicas e truques do 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) | } | } :9: error: could not optimize @tailrec annotated method: it contains a recursive call not in tail position @tailrec def boom(x: Int): Int = { ^ :13: error: could not optimize @tailrec annotated method: it is neither private nor final so can be overridden @tailrec def bang(x: Int): Int = { ^ 

    O compilador Scala otimizará automaticamente qualquer método recursivo de cauda. Se você anotar um método que você acredita ser recursivo à cauda com a anotação @tailrec , o compilador irá avisá-lo se o método na verdade não for recursivo à cauda. Isso torna a anotação @tailrec uma boa ideia, tanto para garantir que um método seja atualmente otimizável e que permaneça otimizável à medida que é modificado.

    Observe que o Scala não considera um método como recursivo de cauda se puder ser substituído. Assim, o método deve ser privado, final, em um object (em oposição a uma class ou característica) ou dentro de outro método a ser otimizado.

    A anotação é scala.annotation.tailrec . Ele triggers um erro do compilador se o método não puder ser otimizado, o que acontece se:

    1. A chamada recursiva não está na posição final
    2. O método pode ser substituído
    3. O método não é final (caso especial do anterior)

    É colocado logo antes do def na definição do método. Funciona no REPL.

    Aqui nós importamos a anotação e tentamos marcar um método como @tailrec .

     scala> import annotation.tailrec import annotation.tailrec scala> @tailrec def length(as: List[_]): Int = as match { | case Nil => 0 | case head :: tail => 1 + length(tail) | } :7: error: could not optimize @tailrec annotated method: it contains a recursive call not in tail position @tailrec def length(as: List[_]): Int = as match { ^ 

    Opa! A última invocação é 1.+() , Não length() ! Vamos reformular o método:

     scala> def length(as: List[_]): Int = { | @tailrec def length0(as: List[_], tally: Int = 0): Int = as match { | case Nil => tally | case head :: tail => length0(tail, tally + 1) | } | length0(as) | } length: (as: List[_])Int 

    Note que length0 é automaticamente privado porque é definido no escopo de outro método.