Можно ли назвать такой код эмуляцией оптимизации хвостовой рекурсии? - Lisp
Формулировка задачи:
Вопрос понятен из названия темы)
Как я правильно понимаю оптимизация хвостовой рекурсии состоит в том чтобы заменить рекурсию со стеком на цикл? Или же я не прав?
Например такой код раскрылся бы в
1 ITERATION
temp_args = 5;
temp = 5 ->next call
2 ITERATION
temp_args = 4
temp_args 20 ->next call
3 ITERATION
temp_args = 3
temp_args 60 ->next call
4 ITERATION
temp_args = 2
temp_args 120 ->next call
5 ITERATION
temp_args = 1
temp_args 120 -> end -> result = temp -> return result;
Object tail_simulation(Expression, condition, args[], doChange){
Object result;
Object temp_args = args;
Object temp = Expression(temp_args);
while(true){
if(condition(temp)){
result = temp;
break;
} else {
temp_args = doChange(temp_args);
temp = Expression(temp_args);
}
}
return result;
}(defun factorial (N)
"Compute the factorial of N."
(if (= N 1)
1
(* N (factorial (- N 1)))))
(factorial 5)Решение задачи: «Можно ли назвать такой код эмуляцией оптимизации хвостовой рекурсии?»
textual
Листинг программы
1 -> (factorial 5) | 2 -> (factorial 4) | | 3 -> (factorial 3) | | | 4 -> (factorial 2) | | | | 5 -> (factorial 1) | | | | | 6 -> (factorial 0) | | | | | 6 <- factorial: 1 | | | | | 6 -> (* 1 1) | | | | | 6 <- *: 1 | | | | 5 <- factorial: 1 | | | | 5 -> (* 2 1) | | | | 5 <- *: 2 | | | 4 <- factorial: 2 | | | 4 -> (* 3 2) | | | 4 <- *: 6 | | 3 <- factorial: 6 | | 3 -> (* 4 6) | | 3 <- *: 24 | 2 <- factorial: 24 | 2 -> (* 5 24) | 2 <- *: 120 1 <- factorial: 120
Объяснение кода листинга программы
В данном коде реализована рекурсивная функция для вычисления факториала. Рекурсия здесь используется для оптимизации вычислений - вместо того, чтобы создавать новый объект для каждого вызова функции, мы вызываем уже существующую функцию с меньшими значениями аргументов. Давайте разберем этот код по шагам:
- Вызов функции (factorial 5). Эта функция вызывает себя же, но уже с аргументом 4.
- Вызов функции (factorial 4). Эта функция также вызывает себя, но уже с аргументом 3.
- Вызов функции (factorial 3). И снова функция вызывает себя, но уже с аргументом 2.
- Вызов функции (factorial 2). И снова функция вызывает себя, но уже с аргументом 1.
- Вызов функции (factorial 1). В этом случае функция просто возвращает 1.
- Вызов функции (factorial 0). Эта функция также возвращает 1.
- Вызов функции (* 1 1). Это вызов оператора умножения, который возвращает 1.
- Вызов функции (* 2 1). Это вызов оператора умножения, который возвращает 2.
- Вызов функции (* 3 2). Это вызов оператора умножения, который возвращает 6.
- Вызов функции (* 4 6). Это вызов оператора умножения, который возвращает 24.
- Вызов функции (* 5 24). Это вызов оператора умножения, который возвращает 120.
- Вызов функции (factorial 120). Эта функция возвращает 120.
- Вызов функции (* 5 24). Это вызов оператора умножения, который возвращает 120.
- Вызов функции (factorial 120). Эта функция возвращает 120. Таким образом, данный код реализует оптимизацию хвостовой рекурсии, поскольку большинство вызовов функцииfactorial не делают ничего, кроме вызова самой себя с меньшими аргументами. Однако, стоит отметить, что в данном случае оптимизация хвостовой рекурсии не приводит к значительному улучшению производительности, поскольку в большинстве случаев будет выполнено не более 5-6 вызовов функции.