Хвостовая рекурсивная функция - это функция, в которой единственный рекурсивный вызов является последним в функции. Не хвостовая рекурсивная функция - это функция, для которой это не так.
Обратная рекурсия - это рекурсия, где в каждом рекурсивном вызове значение параметра меньше, чем на предыдущем шаге. Прямая рекурсия - это рекурсия, в которой она увеличивается с каждым шагом.
Это две ортогональные концепции, то есть прямая рекурсия может быть или не быть хвостовой рекурсией, и то же самое относится к обратной рекурсии.
Например, факториальная функция часто пишется так на императивных языках:
fac = 1
for i from 1 to n:
fac := fac * i
Обычная рекурсивная версия факториала считает в обратном направлении (то есть она вызывает себя с параметром n-1
), однако, если бы вы напрямую перевели вышеприведенное императивное решение, вы бы пришли к рекурсивной версии, которая считает вверх. Это будет выглядеть примерно так:
let fac n =
let rec loop i =
if i >= n
then i
else i * loop (i+1)
in
loop 1
Это прямая рекурсия, и, как вы можете видеть, она немного более громоздка, чем обратный рекурсивный вариант, поскольку требует вспомогательной функции. Теперь это не хвостовая рекурсия, поскольку последний вызов в loop
- это умножение, а не рекурсия. Таким образом, чтобы сделать это хвостовой рекурсией, вы должны сделать что-то вроде этого:
let fac n =
let rec loop acc i =
if i >= n
then acc
else loop (i*acc) (i+1)
in
loop 1 1
Теперь это и прямая рекурсия, и хвостовая рекурсия, потому что рекурсивный вызов - это а) хвостовой вызов и б) вызовы самого себя с большим значением (i+1
).