Extrait du billet de blog « Appels de queue, @tailrec et trampolines »:
- Dans Scala 2.8, vous pourrez également utiliser la nouvelle
@tailrec
annotation pour obtenir des informations sur les méthodes optimisées.
Cette annotation vous permet de marquer des méthodes spécifiques que vous espérez que le compilateur optimisera.
Vous recevrez alors un avertissement s'ils ne sont pas optimisés par le compilateur.
- Dans Scala 2.7 ou version antérieure, vous devrez vous fier à des tests manuels ou à une inspection du bytecode pour déterminer si une méthode a été optimisée.
Exemple:
vous pouvez ajouter une @tailrec
annotation pour être sûr que vos modifications ont fonctionné.
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)
}
}
Et cela fonctionne à partir du REPL (exemple des trucs et astuces 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 = {
^
override
annotation en Java - le code fonctionne sans elle, mais si vous la mettez là, elle vous indique si vous avez fait une erreur.L'annotation est
scala.annotation.tailrec
. Il déclenche une erreur du compilateur si la méthode ne peut pas être optimisée pour l'appel de fin, ce qui se produit si:Il est placé juste avant le
def
dans une définition de méthode. Cela fonctionne dans le REPL.Ici, nous importons l'annotation et essayons de marquer une méthode comme
@tailrec
.Oups! La dernière invocation est
1.+()
, nonlength()
! Reformulons la méthode:Notez que
length0
c'est automatiquement privé car il est défini dans le cadre d'une autre méthode.la source