Изучение Scala и функционального программирования в целом. В следующей реализации факториала с хвостовой рекурсией:
def factorialTailRec(n: Int) : Int = {
@tailrec
def factorialRec(n: Int, f: => Int): Int = {
if (n == 0) f else factorialRec(n - 1, n * f)
}
factorialRec(n, 1)
}
Интересно, есть ли какая-то польза от того, что второй параметр вызывается по value по сравнению с вызовом по name (как я сделал). В первом случае каждый кадр стека обременен продуктом. Во втором случае, если я правильно понимаю, вся цепочка произведений будет перенесена в случай if ( n== 0)
на n
кадре стека, поэтому нам все равно придется выполнять то же количество умножений. К сожалению, это не произведение формы a^n, которое можно вычислить за log_2n шагов путем многократного возведения в квадрат, а произведение членов, каждый раз отличающихся на 1. Поэтому я не вижу никакого возможного способа оптимизации конечного продукта: он все равно потребует умножения O(n) членов.
Это правильно? Эквивалентен ли здесь вызов по значению вызову по имени с точки зрения сложности?