web-dev-qa-db-fra.com

Scala prend-il en charge l'optimisation de la récursivité de la queue?

Scala prend-il en charge l'optimisation de la récursivité de la queue?

62
Roman Kagan

Scala optimise la récursivité de queue au moment de la compilation, comme l'ont dit d'autres affiches. Autrement dit, une fonction récursive de queue est transformée en boucle par le compilateur (une invocation de méthode est transformée en saut), comme le montre la trace de la pile lors de l'exécution d'une fonction récursive de queue.

Essayez l'extrait de code suivant:

def boom(n: Int): Nothing = if(n<=0) throw new Exception else boom(n-1)
boom(10)

et inspectez la trace de la pile. Il ne montrera qu'un seul appel à la fonction boom - donc le bytecode compilé n'est pas récursif.

Il y a une proposition flottant autour de implémenter les appels de queue au niveau de la JVM - ce qui, à mon avis, serait une grande chose à faire, car alors la JVM pourrait faire des optimisations d'exécution, plutôt que simplement compiler des optimisations de temps de la - et pourrait éventuellement signifier une récursion de queue plus flexible. Fondamentalement, un tailcall invoke se comporterait exactement comme une méthode normale invoke mais supprimera la pile de l'appelant lorsque cela est sûr - la spécification de la JVM stipule que les trames de pile doivent être préservées, donc le JIT doit faire un peu analyse de code statique pour savoir si les trames de pile ne seront jamais utilisées.

Son état actuel est proto 80% . Je ne pense pas que ce sera fait à temps pour Java 7 (invokedynamic a une plus grande priorité, et l'implémentation est presque terminée) mais Java 8 pourrait le voir implémenté.

68
Flaviu Cipcigan

Dans Scala 2.8, vous pouvez utiliser @tailrec pour marquer la méthode spécifique que vous attendez du compilateur:

import scala.annotation.tailrec

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

Si une méthode ne peut pas être optimisée, vous obtenez une erreur de compilation.

42

Scala 2.7.x prend en charge l'optimisation des appels de queue pour l'auto-récursivité (une fonction s'appelant elle-même) des méthodes finales et des fonctions locales.

Scala 2.8 pourrait également prendre en charge la bibliothèque pour le trampoline, qui est une technique pour optimiser les fonctions mutuellement récursives.

Une grande quantité d'informations sur l'état de la récursion Scala peut être trouvée dans le blog de Rich Dougherty .

12
Daniel C. Sobral

Seulement dans des cas très simples où la fonction est auto-récursive.

Preuve de la capacité de récursivité de la queue.

Il semble que Scala 2.8 pourrait améliorer la reconnaissance de la récursivité de la queue, cependant.

7
Stefan Kendall