Подтвердить что ты не робот

Поддерживает ли Scala оптимизацию хвостовой рекурсии?

Поддерживает ли Scala оптимизацию хвостовой рекурсии?

4b9b3361

Ответ 1

Scala оптимизирует хвостовую рекурсию во время компиляции, как говорили другие плакаты. То есть, рекурсивная функция хвоста преобразуется в цикл компилятором (метод invoke преобразуется в скачок), как видно из трассировки стека при выполнении хвостовой рекурсивной функции.

Попробуйте следующий фрагмент:

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

и проверьте трассировку стека. Он покажет только один вызов функции boom - поэтому скомпилированный байт-код не является рекурсивным.

Есть предложение, плавающее вокруг реализовать хвостовые вызовы на уровне JVM - что, на мой взгляд, было бы здорово сделать, так как тогда JVM может выполнять оптимизацию во время выполнения, а не просто компилировать оптимизацию времени кода, и, возможно, это означает более гибкую рекурсию хвоста. В принципе, tailcall invoke будет вести себя точно так же, как обычный метод invoke, но сбросит стек вызывающего абонента, если это будет безопасно - спецификация состояний JVM, в которых должны храниться фреймы стека, поэтому JIT должен сделать некоторые статический анализ кода, чтобы узнать, не будут ли использоваться фреймы стека.

Текущий статус proto 80%. Я не думаю, что это будет сделано вовремя для Java 7 (invokedynamic имеет больший приоритет, а реализация почти завершена), но Java 8 может увидеть, что он реализован.

Ответ 2

В Scala 2.8 вы можете использовать @tailrec для обозначения определенного метода, который, как вы надеетесь, оптимизирует компилятор:

import scala.annotation.tailrec

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

Если метод не может быть оптимизирован, вы получите предупреждение.

Ответ 3

Scala 2.7.x поддерживает оптимизацию хвостового вызова для саморекурсии (функция, вызывающая себя) конечных методов и локальных функций.

Scala 2.8 может поставляться с поддержкой библиотеки для батута, что является методом оптимизации взаимно-рекурсивных функций.

Много информации о состоянии рекурсии Scala можно найти в блоге Rich Dougherty.